Class: NIO::ByteBuffer

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/nio/bytebuffer.rb,
ext/nio4r/bytebuffer.c

Overview

Efficient byte buffers for performant I/O operations

Defined Under Namespace

Classes: MarkUnsetError, OverflowError, UnderflowError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(capacity) ⇒ Object

Methods



25
26
27
28
29
# File 'lib/nio/bytebuffer.rb', line 25

def initialize(capacity)
  raise TypeError, "no implicit conversion of #{capacity.class} to Integer" unless capacity.is_a?(Integer)
  @capacity = capacity
  clear
end

Instance Attribute Details

#capacityObject (readonly)

Returns the value of attribute capacity.



21
22
23
# File 'ext/nio4r/bytebuffer.c', line 21

def capacity
  @capacity
end

#limitObject

Returns the value of attribute limit.



19
20
21
# File 'ext/nio4r/bytebuffer.c', line 19

def limit
  @limit
end

#positionObject

Returns the value of attribute position.



17
18
19
# File 'ext/nio4r/bytebuffer.c', line 17

def position
  @position
end

Instance Method Details

#<<(str) ⇒ self

Add a String to the buffer

Returns:

  • (self)

Raises:



121
122
123
124
125
126
# File 'lib/nio/bytebuffer.rb', line 121

def <<(str)
  raise OverflowError, "buffer is full" if str.length > @limit - @position
  @buffer[@position...str.length] = str
  @position += str.length
  self
end

#[](index) ⇒ Integer

Obtain the byte at a given index in the buffer as an Integer

Returns:

  • (Integer)

    byte at the given index

Raises:

  • (ArgumentError)

    index is invalid (either negative or larger than limit)



109
110
111
112
113
114
# File 'lib/nio/bytebuffer.rb', line 109

def [](index)
  raise ArgumentError, "negative index given" if index < 0
  raise ArgumentError, "specified index exceeds limit" if index >= @limit

  @buffer.bytes[index]
end

#clearObject

Clear the buffer, resetting it to the default state



32
33
34
35
36
37
38
39
# File 'lib/nio/bytebuffer.rb', line 32

def clear
  @buffer   = ("\0" * @capacity).force_encoding(Encoding::BINARY)
  @position = 0
  @limit    = @capacity
  @mark     = nil

  self
end

#compactObject

Move data between the position and limit to the beginning of the buffer Sets the position to the end of the moved data, and the limit to the capacity



194
195
196
197
198
199
# File 'lib/nio/bytebuffer.rb', line 194

def compact
  @buffer[0...(@limit - @position)] = @buffer[@position...@limit]
  @position = @limit - @position
  @limit = capacity
  self
end

#each(&block) ⇒ self

Iterate over the bytes in the buffer (as Integers)

Returns:

  • (self)


204
205
206
# File 'lib/nio/bytebuffer.rb', line 204

def each(&block)
  @buffer[0...@limit].each_byte(&block)
end

#flipObject

Set the buffer’s current position as the limit and set the position to 0



163
164
165
166
167
168
# File 'lib/nio/bytebuffer.rb', line 163

def flip
  @limit = @position
  @position = 0
  @mark = nil
  self
end

#full?true, false

Does the ByteBuffer have any space remaining?

Returns:

  • (true, false)


85
86
87
# File 'lib/nio/bytebuffer.rb', line 85

def full?
  remaining.zero?
end

#get(length = remaining) ⇒ String

Obtain the requested number of bytes from the buffer, advancing the position. If no length is given, all remaining bytes are consumed.

Returns:

  • (String)

    bytes read from buffer

Raises:



95
96
97
98
99
100
101
102
# File 'lib/nio/bytebuffer.rb', line 95

def get(length = remaining)
  raise ArgumentError, "negative length given" if length < 0
  raise UnderflowError, "not enough data in buffer" if length > @limit - @position

  result = @buffer[@position...length]
  @position += length
  result
end

#inspectString

Inspect the state of the buffer

Returns:

  • (String)

    string describing the state of the buffer



211
212
213
214
215
216
217
218
219
220
# File 'lib/nio/bytebuffer.rb', line 211

def inspect
  format(
    "#<%s:0x%x @position=%d @limit=%d @capacity=%d>",
    self.class,
    object_id << 1,
    @position,
    @limit,
    @capacity
  )
end

#markObject

Mark a position to return to using the ‘#reset` method



178
179
180
181
# File 'lib/nio/bytebuffer.rb', line 178

def mark
  @mark = @position
  self
end

#read_from(io) ⇒ Integer

Perform a non-blocking read from the given IO object into the buffer Reads as much data as is immediately available and returns

Parameters:

  • Ruby (IO)

    IO object to read from

Returns:

  • (Integer)

    number of bytes read (0 if none were available)

Raises:



134
135
136
137
138
139
140
141
142
143
# File 'lib/nio/bytebuffer.rb', line 134

def read_from(io)
  nbytes = @limit - @position
  raise OverflowError, "buffer is full" if nbytes.zero?

  bytes_read = IO.try_convert(io).read_nonblock(nbytes, exception: false)
  return 0 if bytes_read == :wait_readable

  self << bytes_read
  bytes_read.length
end

#remainingInteger

Number of bytes remaining in the buffer before the limit

Returns:

  • (Integer)

    number of bytes remaining



78
79
80
# File 'lib/nio/bytebuffer.rb', line 78

def remaining
  @limit - @position
end

#resetObject

Reset position to the previously marked location

Raises:



186
187
188
189
190
# File 'lib/nio/bytebuffer.rb', line 186

def reset
  raise MarkUnsetError, "mark has not been set" unless @mark
  @position = @mark
  self
end

#rewindObject

Set the buffer’s current position to 0, leaving the limit unchanged



171
172
173
174
175
# File 'lib/nio/bytebuffer.rb', line 171

def rewind
  @position = 0
  @mark = nil
  self
end

#sizeObject



21
# File 'ext/nio4r/bytebuffer.c', line 21

static VALUE NIO_ByteBuffer_capacity(VALUE self);

#write_to(io) ⇒ Integer

Perform a non-blocking write of the buffer’s contents to the given I/O object Writes as much data as is immediately possible and returns

Parameters:

  • Ruby (IO)

    IO object to write to

Returns:

  • (Integer)

    number of bytes written (0 if the write would block)

Raises:



151
152
153
154
155
156
157
158
159
160
# File 'lib/nio/bytebuffer.rb', line 151

def write_to(io)
  nbytes = @limit - @position
  raise UnderflowError, "no data remaining in buffer" if nbytes.zero?

  bytes_written = IO.try_convert(io).write_nonblock(@buffer[@position...@limit], exception: false)
  return 0 if bytes_written == :wait_writable

  @position += bytes_written
  bytes_written
end