lib/bindata/buffer.rb in bindata-2.4.15 vs lib/bindata/buffer.rb in bindata-2.5.0
- old
+ new
@@ -39,12 +39,12 @@
# uint8 :len
# string :str, length: :len
# end
# end
# end
- #
#
+ #
# == Parameters
#
# Parameters may be provided at initialisation to control the behaviour of
# an object. These params are:
#
@@ -78,31 +78,109 @@
def snapshot
@type.snapshot
end
- def respond_to?(symbol, include_private = false) #:nodoc:
- @type.respond_to?(symbol, include_private) || super
+ def respond_to_missing?(symbol, include_all = false) # :nodoc:
+ @type.respond_to?(symbol, include_all) || super
end
- def method_missing(symbol, *args, &block) #:nodoc:
+ def method_missing(symbol, *args, &block) # :nodoc:
@type.__send__(symbol, *args, &block)
end
- def do_read(io) #:nodoc:
- io.with_buffer(eval_parameter(:length)) do
- @type.do_read(io)
+ def do_read(io) # :nodoc:
+ buf_len = eval_parameter(:length)
+ io.transform(BufferIO.new(buf_len)) do |transformed_io, _|
+ @type.do_read(transformed_io)
end
end
- def do_write(io) #:nodoc:
- io.with_buffer(eval_parameter(:length)) do
- @type.do_write(io)
+ def do_write(io) # :nodoc:
+ buf_len = eval_parameter(:length)
+ io.transform(BufferIO.new(buf_len)) do |transformed_io, _|
+ @type.do_write(transformed_io)
end
end
- def do_num_bytes #:nodoc:
+ def do_num_bytes # :nodoc:
eval_parameter(:length)
+ end
+
+ # Transforms the IO stream to restrict access inside
+ # a buffer of specified length.
+ class BufferIO < IO::Transform
+ def initialize(length)
+ super()
+ @bytes_remaining = length
+ end
+
+ def before_transform
+ @buf_start = offset
+ @buf_end = @buf_start + @bytes_remaining
+ end
+
+ def num_bytes_remaining
+ [@bytes_remaining, super].min
+ rescue IOError
+ @bytes_remaining
+ end
+
+ def skip(n)
+ nbytes = buffer_limited_n(n)
+ @bytes_remaining -= nbytes
+
+ chain_skip(nbytes)
+ end
+
+ def seek_abs(n)
+ if n < @buf_start || n >= @buf_end
+ raise IOError, "can not seek to abs_offset outside of buffer"
+ end
+
+ @bytes_remaining -= (n - offset)
+ chain_seek_abs(n)
+ end
+
+ def read(n)
+ nbytes = buffer_limited_n(n)
+ @bytes_remaining -= nbytes
+
+ chain_read(nbytes)
+ end
+
+ def write(data)
+ nbytes = buffer_limited_n(data.size)
+ @bytes_remaining -= nbytes
+ if nbytes < data.size
+ data = data[0, nbytes]
+ end
+
+ chain_write(data)
+ end
+
+ def after_read_transform
+ read(nil)
+ end
+
+ def after_write_transform
+ write("\x00" * @bytes_remaining)
+ end
+
+ def buffer_limited_n(n)
+ if n.nil?
+ @bytes_remaining
+ elsif n.positive?
+ limit = @bytes_remaining
+ n > limit ? limit : n
+# uncomment if we decide to allow backwards skipping
+# elsif n.negative?
+# limit = @bytes_remaining + @buf_start - @buf_end
+# n < limit ? limit : n
+ else
+ 0
+ end
+ end
end
end
class BufferArgProcessor < BaseArgProcessor
include MultiFieldArgSeparator