class IO::Buffer::Slice
A zero-copy, parent-relative view of an IO::Buffer or another Slice. Create a view with IO::Buffer#slice or IO::Buffer::Slice.new:
buffer = IO::Buffer.new(6) buffer.set_string("abcdef") parent = buffer.slice(1, 4) child = parent.slice(1, 2) child.source.equal?(parent) # => true child.get_string # => "cd" parent.advance(1) child.get_string # => "de"
A slice retains its immediate source and follows that source’s current view. Its range is valid only while every parent is valid and the range fits within its source. Moving the backing allocation does not itself invalidate a slice. Shrinking a parent can invalidate descendants; growing it again can restore their validity.
Slice inherits Buffer’s byte-access interface but does not manage storage. Resizing a slice only changes its extent within its parent’s bounds, and advancing it consumes bytes from the front of its view. Neither operation allocates or releases storage. Slice has no free or transfer method, nor Storage’s predicates such as mapped? or internal?.
Writes modify the source’s bytes and respect its current permissions. Locking a slice protects the backing allocation; locked? reports that shared lock state. Locked or read-only views may still be resized or advanced, but frozen views cannot change their range. Locking does not serialize access to bytes or view metadata.
Duplicating or cloning a Slice copies its view rather than its bytes. Both Slice and Storage are subclasses of IO::Buffer.
Public Class Methods
static VALUE
io_buffer_slice_initialize(int argc, VALUE *argv, VALUE self)
{
rb_check_frozen(self);
rb_check_arity(argc, 1, 3);
struct rb_io_buffer_view *slice = get_io_buffer_view(self);
if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");
VALUE source = argv[0];
size_t offset, length;
struct rb_io_buffer_view *parent = io_buffer_extract_offset_length(source, argc-1, argv+1, &offset, &length);
io_buffer_validate_range(parent, offset, length);
slice = get_io_buffer_view(self);
if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");
slice->base = (void *)(uintptr_t)offset;
slice->size = length;
RB_OBJ_WRITE(self, &slice->source, source);
return self;
}
Public Instance Methods
Source
static VALUE
io_buffer_slice_initialize_copy(VALUE self, VALUE other)
{
if (self == other) return self;
rb_check_frozen(self);
struct rb_io_buffer_view *slice = get_io_buffer_view(self);
const struct rb_io_buffer_view *original = get_io_buffer_view(other);
if (!io_buffer_slice_p(original)) rb_raise(rb_eTypeError, "Expected IO::Buffer::Slice!");
if (!NIL_P(slice->source)) rb_raise(rb_eRuntimeError, "Slice is already initialized!");
slice->base = original->base;
slice->size = original->size;
slice->flags = original->flags;
RB_OBJ_WRITE(self, &slice->source, original->source);
return self;
}
Copies the view, retaining the same source, offset, and size without copying the underlying bytes. Advancing or resizing the copy does not change the original view; writes through either view affect shared storage.
buffer = IO::Buffer.new(6) buffer.set_string("abcdef") slice = buffer.slice(1, 3) copy = slice.dup copy.source.equal?(slice.source) # => true copy.advance(1) copy.get_string # => "cd" slice.get_string # => "bcd" copy.set_string("XY") buffer.get_string # => "abXYef"
This differs from IO::Buffer::Storage#dup, which copies the bytes into independent storage. The usual Object#dup and Object#clone frozen-state rules apply.
Source
static VALUE
io_buffer_resize(VALUE self, VALUE size)
{
rb_check_frozen(self);
rb_io_buffer_resize(self, io_buffer_extract_size(size));
return self;
}
Resizes a buffer to a new_size bytes, preserving its content. Depending on the old and new size, the memory area associated with the buffer might be either extended, or rellocated at different address with content being copied.
buffer = IO::Buffer.new(4) buffer.set_string("test", 0) buffer.resize(8) # resize to 8 bytes # => # #<IO::Buffer 0x0000555f5d1a1630+8 INTERNAL> # 0x00000000 74 65 73 74 00 00 00 00 test....
When the buffer is a slice, resizing changes the size of the view without modifying the source buffer or allocating new storage. The resized view must remain within the source buffer. Growing the view exposes the existing bytes in the source; they are not cleared. Because the source allocation does not change, a slice can be resized while its source is locked.
External owning buffers (created with ::for), and locked owning buffers cannot be resized. Frozen buffers cannot be resized.