adsp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +21 -0
- data/README.md +300 -0
- data/lib/adsp/error.rb +14 -0
- data/lib/adsp/file.rb +76 -0
- data/lib/adsp/option.rb +51 -0
- data/lib/adsp/stream/abstract.rb +206 -0
- data/lib/adsp/stream/delegates.rb +39 -0
- data/lib/adsp/stream/raw/abstract.rb +69 -0
- data/lib/adsp/stream/raw/compressor.rb +110 -0
- data/lib/adsp/stream/raw/decompressor.rb +80 -0
- data/lib/adsp/stream/raw/native_compressor.rb +58 -0
- data/lib/adsp/stream/raw/native_decompressor.rb +44 -0
- data/lib/adsp/stream/reader.rb +234 -0
- data/lib/adsp/stream/reader_helpers.rb +219 -0
- data/lib/adsp/stream/stat.rb +80 -0
- data/lib/adsp/stream/writer.rb +206 -0
- data/lib/adsp/stream/writer_helpers.rb +102 -0
- data/lib/adsp/string.rb +58 -0
- data/lib/adsp/validation.rb +46 -0
- data/lib/adsp/version.rb +7 -0
- data/lib/adsp.rb +8 -0
- data/test/common.rb +108 -0
- data/test/coverage_helper.rb +18 -0
- data/test/file.test.rb +120 -0
- data/test/minitest.rb +20 -0
- data/test/mock/common.rb +57 -0
- data/test/mock/file.rb +60 -0
- data/test/mock/stream/raw/compressor.rb +20 -0
- data/test/mock/stream/raw/decompressor.rb +20 -0
- data/test/mock/stream/raw/native_compressor.rb +82 -0
- data/test/mock/stream/raw/native_decompressor.rb +70 -0
- data/test/mock/stream/reader.rb +18 -0
- data/test/mock/stream/writer.rb +18 -0
- data/test/mock/string.rb +44 -0
- data/test/option.rb +66 -0
- data/test/stream/abstract.rb +125 -0
- data/test/stream/minitar.test.rb +50 -0
- data/test/stream/raw/abstract.rb +45 -0
- data/test/stream/raw/compressor.test.rb +166 -0
- data/test/stream/raw/decompressor.test.rb +166 -0
- data/test/stream/reader.test.rb +643 -0
- data/test/stream/reader_helpers.test.rb +421 -0
- data/test/stream/writer.test.rb +610 -0
- data/test/stream/writer_helpers.test.rb +267 -0
- data/test/string.test.rb +95 -0
- data/test/validation.rb +71 -0
- data/test/version.test.rb +18 -0
- metadata +274 -0
data/lib/adsp.rb
ADDED
data/test/common.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "parallel"
|
5
|
+
require "securerandom"
|
6
|
+
require "tempfile"
|
7
|
+
|
8
|
+
require_relative "coverage_helper"
|
9
|
+
|
10
|
+
module ADSP
|
11
|
+
module Test
|
12
|
+
module Common
|
13
|
+
BASE_PATH = ::File.expand_path(::File.join(::File.dirname(__FILE__), "..")).freeze
|
14
|
+
TEMP_PATH = ::File.join(BASE_PATH, "tmp").freeze
|
15
|
+
|
16
|
+
SOURCE_PATH = ::File.join(TEMP_PATH, "source").freeze
|
17
|
+
ARCHIVE_PATH = ::File.join(TEMP_PATH, "archive").freeze
|
18
|
+
|
19
|
+
[
|
20
|
+
SOURCE_PATH,
|
21
|
+
ARCHIVE_PATH
|
22
|
+
]
|
23
|
+
.each { |path| FileUtils.touch path }
|
24
|
+
|
25
|
+
def self.get_path(path, suffix)
|
26
|
+
"#{path}_#{suffix}"
|
27
|
+
end
|
28
|
+
|
29
|
+
ENCODINGS = %w[
|
30
|
+
binary
|
31
|
+
UTF-8
|
32
|
+
UTF-16LE
|
33
|
+
]
|
34
|
+
.map { |encoding_name| ::Encoding.find encoding_name }
|
35
|
+
.freeze
|
36
|
+
|
37
|
+
TRANSCODE_OPTIONS = {
|
38
|
+
:invalid => :replace,
|
39
|
+
:undef => :replace,
|
40
|
+
:replace => "?"
|
41
|
+
}
|
42
|
+
.freeze
|
43
|
+
|
44
|
+
def self.generate_texts(*sources)
|
45
|
+
sources.flat_map do |source|
|
46
|
+
ENCODINGS.map do |encoding|
|
47
|
+
source.encode encoding, **TRANSCODE_OPTIONS
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
TEXTS = generate_texts(
|
53
|
+
"",
|
54
|
+
::SecureRandom.random_bytes(1 << 8) # 256 B
|
55
|
+
)
|
56
|
+
.freeze
|
57
|
+
|
58
|
+
LARGE_TEXTS = generate_texts(
|
59
|
+
::SecureRandom.random_bytes(1 << 21) # 2 MB
|
60
|
+
)
|
61
|
+
.freeze
|
62
|
+
|
63
|
+
# It is better to have text lengths not divisible by portion lengths.
|
64
|
+
PORTION_LENGTHS = [
|
65
|
+
10**2,
|
66
|
+
5 * (10**2)
|
67
|
+
]
|
68
|
+
.freeze
|
69
|
+
|
70
|
+
# It is better to have large text lengths not divisible by large portion lengths.
|
71
|
+
LARGE_PORTION_LENGTHS = [
|
72
|
+
10**6,
|
73
|
+
5 * (10**6)
|
74
|
+
]
|
75
|
+
.freeze
|
76
|
+
|
77
|
+
# We need at least 2 threads for testing multiple threads support.
|
78
|
+
THREADS_COUNT = [Parallel.processor_count, 2].max.freeze
|
79
|
+
|
80
|
+
def self.parallel(producer, &_block)
|
81
|
+
Parallel.each producer, :in_threads => THREADS_COUNT do |item|
|
82
|
+
yield item, Parallel.worker_number
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.parallel_options(generator, &block)
|
87
|
+
producer = proc do
|
88
|
+
next Parallel::Stop if generator.finished?
|
89
|
+
|
90
|
+
generator.next
|
91
|
+
end
|
92
|
+
|
93
|
+
parallel producer, &block
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.file_can_be_used_nonblock?
|
97
|
+
::File.open(::Tempfile.new, "w") do |file|
|
98
|
+
file.write_nonblock "text"
|
99
|
+
end
|
100
|
+
rescue Errno::EBADF
|
101
|
+
# Nonblock operations with files are not available on Windows.
|
102
|
+
false
|
103
|
+
else
|
104
|
+
true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
if ENV["CI"]
|
5
|
+
require "codecov"
|
6
|
+
require "simplecov"
|
7
|
+
|
8
|
+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
|
9
|
+
[
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
11
|
+
SimpleCov::Formatter::Codecov
|
12
|
+
]
|
13
|
+
)
|
14
|
+
|
15
|
+
SimpleCov.start do
|
16
|
+
add_filter %r{^/test/}
|
17
|
+
end
|
18
|
+
end
|
data/test/file.test.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/file"
|
5
|
+
|
6
|
+
require_relative "common"
|
7
|
+
require_relative "minitest"
|
8
|
+
require_relative "mock/file"
|
9
|
+
require_relative "option"
|
10
|
+
require_relative "validation"
|
11
|
+
|
12
|
+
module ADSP
|
13
|
+
module Test
|
14
|
+
class File < Minitest::Test
|
15
|
+
Option = Test::Option
|
16
|
+
Target = Mock::File
|
17
|
+
|
18
|
+
SOURCE_PATH = Common::SOURCE_PATH
|
19
|
+
ARCHIVE_PATH = Common::ARCHIVE_PATH
|
20
|
+
TEXTS = Common::TEXTS
|
21
|
+
LARGE_TEXTS = Common::LARGE_TEXTS
|
22
|
+
|
23
|
+
BUFFER_LENGTH_NAMES = %i[source_buffer_length destination_buffer_length].freeze
|
24
|
+
BUFFER_LENGTH_MAPPING = {
|
25
|
+
:source_buffer_length => :destination_buffer_length,
|
26
|
+
:destination_buffer_length => :source_buffer_length
|
27
|
+
}
|
28
|
+
.freeze
|
29
|
+
|
30
|
+
def test_invalid_arguments
|
31
|
+
Validation::INVALID_STRINGS.each do |invalid_path|
|
32
|
+
assert_raises ValidateError do
|
33
|
+
Target.compress invalid_path, ARCHIVE_PATH
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_raises ValidateError do
|
37
|
+
Target.compress SOURCE_PATH, invalid_path
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_raises ValidateError do
|
41
|
+
Target.decompress invalid_path, SOURCE_PATH
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_raises ValidateError do
|
45
|
+
Target.decompress ARCHIVE_PATH, invalid_path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
get_invalid_compressor_options do |invalid_options|
|
50
|
+
assert_raises ValidateError do
|
51
|
+
Target.compress SOURCE_PATH, ARCHIVE_PATH, invalid_options
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
get_invalid_decompressor_options do |invalid_options|
|
56
|
+
assert_raises ValidateError do
|
57
|
+
Target.decompress ARCHIVE_PATH, SOURCE_PATH, invalid_options
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_texts
|
63
|
+
parallel_compressor_options do |compressor_options, worker_index|
|
64
|
+
source_path = Common.get_path SOURCE_PATH, worker_index
|
65
|
+
archive_path = Common.get_path ARCHIVE_PATH, worker_index
|
66
|
+
|
67
|
+
TEXTS.each do |text|
|
68
|
+
::File.write source_path, text, :mode => "wb"
|
69
|
+
Target.compress source_path, archive_path, compressor_options
|
70
|
+
|
71
|
+
get_compatible_decompressor_options compressor_options do |decompressor_options|
|
72
|
+
Target.decompress archive_path, source_path, decompressor_options
|
73
|
+
|
74
|
+
decompressed_text = ::File.read source_path, :mode => "rb"
|
75
|
+
decompressed_text.force_encoding text.encoding
|
76
|
+
|
77
|
+
assert_equal text, decompressed_text
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_large_texts
|
84
|
+
Common.parallel LARGE_TEXTS do |text, worker_index|
|
85
|
+
source_path = Common.get_path SOURCE_PATH, worker_index
|
86
|
+
archive_path = Common.get_path ARCHIVE_PATH, worker_index
|
87
|
+
|
88
|
+
::File.write source_path, text, :mode => "wb"
|
89
|
+
Target.compress source_path, archive_path
|
90
|
+
Target.decompress archive_path, source_path
|
91
|
+
|
92
|
+
decompressed_text = ::File.read source_path, :mode => "rb"
|
93
|
+
decompressed_text.force_encoding text.encoding
|
94
|
+
|
95
|
+
assert_equal text, decompressed_text
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# -----
|
100
|
+
|
101
|
+
def get_invalid_compressor_options(&block)
|
102
|
+
self.class::Option.get_invalid_compressor_options BUFFER_LENGTH_NAMES, &block
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_invalid_decompressor_options(&block)
|
106
|
+
self.class::Option.get_invalid_decompressor_options BUFFER_LENGTH_NAMES, &block
|
107
|
+
end
|
108
|
+
|
109
|
+
def parallel_compressor_options(&block)
|
110
|
+
Common.parallel_options self.class::Option.get_compressor_options_generator(BUFFER_LENGTH_NAMES), &block
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_compatible_decompressor_options(compressor_options, &block)
|
114
|
+
self.class::Option.get_compatible_decompressor_options compressor_options, BUFFER_LENGTH_MAPPING, &block
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
Minitest << File
|
119
|
+
end
|
120
|
+
end
|
data/test/minitest.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "minitest"
|
5
|
+
require "minitest/autorun"
|
6
|
+
|
7
|
+
module Minitest
|
8
|
+
Minitest.module_eval do
|
9
|
+
class << self
|
10
|
+
def <<(klass)
|
11
|
+
Runnable.runnables << klass unless Runnable.runnables.include? klass
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Runnable.instance_eval do
|
18
|
+
def self.inherited(_klass); end # rubocop:disable Lint/MissingSuper
|
19
|
+
end
|
20
|
+
end
|
data/test/mock/common.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/string"
|
5
|
+
|
6
|
+
require_relative "../common"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
module Common
|
12
|
+
DEFAULT_DESTINATION_BUFFER_LENGTH = 1 << 18 # 256 KB
|
13
|
+
|
14
|
+
# Flipping bytes and packing them as 16-bit values in network byte order.
|
15
|
+
# This method will make compressed data bytesize more than original bytesize.
|
16
|
+
# It will help to improve testing coverage.
|
17
|
+
def self.native_compress(source, destination_buffer_length)
|
18
|
+
source_length = source.bytesize
|
19
|
+
destination_buffer_length = DEFAULT_DESTINATION_BUFFER_LENGTH if destination_buffer_length.zero?
|
20
|
+
|
21
|
+
bytes_read =
|
22
|
+
if destination_buffer_length.nil?
|
23
|
+
source_length
|
24
|
+
else
|
25
|
+
[source_length, destination_buffer_length / 2].min
|
26
|
+
end
|
27
|
+
|
28
|
+
result = source
|
29
|
+
.byteslice(0, bytes_read)
|
30
|
+
.unpack("C*")
|
31
|
+
.map { |byte| byte ^ 0xFF }
|
32
|
+
.pack "n*"
|
33
|
+
[result, bytes_read]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.native_decompress(source, destination_buffer_length)
|
37
|
+
source_length = source.bytesize / 2 * 2
|
38
|
+
destination_buffer_length = DEFAULT_DESTINATION_BUFFER_LENGTH if destination_buffer_length.zero?
|
39
|
+
|
40
|
+
bytes_read =
|
41
|
+
if destination_buffer_length.nil?
|
42
|
+
source_length
|
43
|
+
else
|
44
|
+
[source_length, destination_buffer_length * 2].min
|
45
|
+
end
|
46
|
+
|
47
|
+
result = source
|
48
|
+
.byteslice(0, bytes_read)
|
49
|
+
.unpack("n*")
|
50
|
+
.map { |byte| byte ^ 0xFF }
|
51
|
+
.pack "C*"
|
52
|
+
[result, bytes_read]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/test/mock/file.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/file"
|
5
|
+
|
6
|
+
require_relative "./common"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
class File < ADSP::File
|
12
|
+
PORTION_LENGTH = 10**6
|
13
|
+
|
14
|
+
def self.native_compress_io(source_io, destination_io, options)
|
15
|
+
destination_buffer_length = options[:destination_buffer_length]
|
16
|
+
source = "".b
|
17
|
+
|
18
|
+
loop do
|
19
|
+
begin
|
20
|
+
source << source_io.readpartial(PORTION_LENGTH)
|
21
|
+
rescue ::EOFError
|
22
|
+
break
|
23
|
+
end
|
24
|
+
|
25
|
+
until source.empty?
|
26
|
+
data, bytes_read = Common.native_compress source, destination_buffer_length
|
27
|
+
source = source.byteslice bytes_read, source.bytesize - bytes_read
|
28
|
+
|
29
|
+
destination_io.write data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.native_decompress_io(source_io, destination_io, options)
|
37
|
+
destination_buffer_length = options[:destination_buffer_length]
|
38
|
+
source = "".b
|
39
|
+
|
40
|
+
loop do
|
41
|
+
begin
|
42
|
+
source << source_io.readpartial(PORTION_LENGTH)
|
43
|
+
rescue ::EOFError
|
44
|
+
break
|
45
|
+
end
|
46
|
+
|
47
|
+
until source.empty?
|
48
|
+
data, bytes_read = Common.native_decompress source, destination_buffer_length
|
49
|
+
source = source.byteslice bytes_read, source.bytesize - bytes_read
|
50
|
+
|
51
|
+
destination_io.write data
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/stream/raw/compressor"
|
5
|
+
|
6
|
+
require_relative "native_compressor"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
module Stream
|
12
|
+
module Raw
|
13
|
+
class Compressor < ADSP::Stream::Raw::Compressor
|
14
|
+
NativeCompressor = Raw::NativeCompressor
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/stream/raw/decompressor"
|
5
|
+
|
6
|
+
require_relative "native_decompressor"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
module Stream
|
12
|
+
module Raw
|
13
|
+
class Decompressor < ADSP::Stream::Raw::Decompressor
|
14
|
+
NativeDecompressor = Raw::NativeDecompressor
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/error"
|
5
|
+
require "adsp/validation"
|
6
|
+
|
7
|
+
require_relative "../../common"
|
8
|
+
|
9
|
+
module ADSP
|
10
|
+
module Test
|
11
|
+
module Mock
|
12
|
+
module Stream
|
13
|
+
module Raw
|
14
|
+
class NativeCompressor
|
15
|
+
def initialize(options)
|
16
|
+
ADSP::Validation.validate_hash options
|
17
|
+
|
18
|
+
destination_buffer_length = options[:destination_buffer_length]
|
19
|
+
ADSP::Validation.validate_not_negative_integer destination_buffer_length
|
20
|
+
|
21
|
+
destination_buffer_length = Common::DEFAULT_DESTINATION_BUFFER_LENGTH \
|
22
|
+
if destination_buffer_length.zero?
|
23
|
+
|
24
|
+
@destination_buffer = "".b
|
25
|
+
@destination_buffer_length = destination_buffer_length
|
26
|
+
|
27
|
+
@is_closed = false
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(source)
|
31
|
+
ADSP::Validation.validate_string source
|
32
|
+
|
33
|
+
do_not_use_after_close
|
34
|
+
|
35
|
+
remaining_destination_buffer_length = @destination_buffer_length - @destination_buffer.bytesize
|
36
|
+
return [0, true] if remaining_destination_buffer_length.zero?
|
37
|
+
|
38
|
+
data, bytes_read = Common.native_compress source, remaining_destination_buffer_length
|
39
|
+
needs_more_destination = bytes_read < source.bytesize
|
40
|
+
@destination_buffer << data
|
41
|
+
|
42
|
+
[bytes_read, needs_more_destination]
|
43
|
+
end
|
44
|
+
|
45
|
+
def read_result
|
46
|
+
do_not_use_after_close
|
47
|
+
|
48
|
+
result = @destination_buffer
|
49
|
+
@destination_buffer = "".b
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def flush
|
55
|
+
do_not_use_after_close
|
56
|
+
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def finish
|
61
|
+
do_not_use_after_close
|
62
|
+
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def close
|
67
|
+
do_not_use_after_close
|
68
|
+
|
69
|
+
@is_closed = true
|
70
|
+
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
protected def do_not_use_after_close
|
75
|
+
raise UsedAfterCloseError if @is_closed
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/error"
|
5
|
+
require "adsp/validation"
|
6
|
+
|
7
|
+
require_relative "../../common"
|
8
|
+
|
9
|
+
module ADSP
|
10
|
+
module Test
|
11
|
+
module Mock
|
12
|
+
module Stream
|
13
|
+
module Raw
|
14
|
+
class NativeDecompressor
|
15
|
+
def initialize(options)
|
16
|
+
ADSP::Validation.validate_hash options
|
17
|
+
|
18
|
+
destination_buffer_length = options[:destination_buffer_length]
|
19
|
+
ADSP::Validation.validate_not_negative_integer destination_buffer_length
|
20
|
+
|
21
|
+
destination_buffer_length = Common::DEFAULT_DESTINATION_BUFFER_LENGTH \
|
22
|
+
if destination_buffer_length.zero?
|
23
|
+
|
24
|
+
@destination_buffer = "".b
|
25
|
+
@destination_buffer_length = destination_buffer_length
|
26
|
+
|
27
|
+
@is_closed = false
|
28
|
+
end
|
29
|
+
|
30
|
+
def read(source)
|
31
|
+
ADSP::Validation.validate_string source
|
32
|
+
|
33
|
+
do_not_use_after_close
|
34
|
+
|
35
|
+
remaining_destination_buffer_length = @destination_buffer_length - @destination_buffer.bytesize
|
36
|
+
return [0, true] if remaining_destination_buffer_length.zero?
|
37
|
+
|
38
|
+
data, bytes_read = Common.native_decompress source, remaining_destination_buffer_length
|
39
|
+
needs_more_destination = bytes_read < source.bytesize
|
40
|
+
@destination_buffer << data
|
41
|
+
|
42
|
+
[bytes_read, needs_more_destination]
|
43
|
+
end
|
44
|
+
|
45
|
+
def read_result
|
46
|
+
do_not_use_after_close
|
47
|
+
|
48
|
+
result = @destination_buffer
|
49
|
+
@destination_buffer = "".b
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def close
|
55
|
+
do_not_use_after_close
|
56
|
+
|
57
|
+
@is_closed = true
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
protected def do_not_use_after_close
|
63
|
+
raise UsedAfterCloseError if @is_closed
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/stream/reader"
|
5
|
+
|
6
|
+
require_relative "raw/decompressor"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
module Stream
|
12
|
+
class Reader < ADSP::Stream::Reader
|
13
|
+
RawDecompressor = Mock::Stream::Raw::Decompressor
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/stream/writer"
|
5
|
+
|
6
|
+
require_relative "raw/compressor"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
module Stream
|
12
|
+
class Writer < ADSP::Stream::Writer
|
13
|
+
RawCompressor = Mock::Stream::Raw::Compressor
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/mock/string.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Abstract data stream processor.
|
2
|
+
# Copyright (c) 2021 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "adsp/string"
|
5
|
+
|
6
|
+
require_relative "./common"
|
7
|
+
|
8
|
+
module ADSP
|
9
|
+
module Test
|
10
|
+
module Mock
|
11
|
+
class String < ADSP::String
|
12
|
+
def self.native_compress_string(source, options)
|
13
|
+
destination_buffer_length = options[:destination_buffer_length]
|
14
|
+
result = "".b
|
15
|
+
|
16
|
+
loop do
|
17
|
+
data, bytes_read = Common.native_compress source, destination_buffer_length
|
18
|
+
source = source.byteslice bytes_read, source.bytesize - bytes_read
|
19
|
+
result << data
|
20
|
+
|
21
|
+
break if source.bytesize.zero?
|
22
|
+
end
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.native_decompress_string(source, options)
|
28
|
+
destination_buffer_length = options[:destination_buffer_length]
|
29
|
+
result = "".b
|
30
|
+
|
31
|
+
loop do
|
32
|
+
data, bytes_read = Common.native_decompress source, destination_buffer_length
|
33
|
+
source = source.byteslice bytes_read, source.bytesize - bytes_read
|
34
|
+
result << data
|
35
|
+
|
36
|
+
break if source.bytesize.zero?
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|