io-stream 0.4.3 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e86dd2d0db65582e6b9655493776e1f3fa16c8d22af92d40c7c2f1ae374c7ee
4
- data.tar.gz: e6299a23d03c263361f04bae8ec29c3d0b70c2f19d6cdfe64ff601d6b7bb7c64
3
+ metadata.gz: e7580fa6412067d9c5e341d3f81de6f9cd8134cc04fb1b2666bafc0a9685cc99
4
+ data.tar.gz: 76040e83616e06be4c7c0bbdfd89d019542b8d5eaa44c56af5e474acda870983
5
5
  SHA512:
6
- metadata.gz: 16d2aff35b208b029c2b917cd6a423d5ee54547939a39e5575f2641d8060b793a03a5a0903a885216142d99369ba80f8941d35ab07739a11c95d2c98dfa1d3cd
7
- data.tar.gz: af90134348a217f72fe90dea4cab0c2c4e7fc6b7a2c27345b865642191c9aa0bdda16b2e1856114d1e42bbf7f9c6be7bb506daa8cb9724baae2fdf1534dcc85e
6
+ metadata.gz: 9ac128c5e456067d97b9477ed715fc2d4b0698b3d01e2cb6884dfa2b28128b09a860cba4480f8b0a161c2d13c4ac956c00ddafee1b949f8f63f602e7ad277185
7
+ data.tar.gz: a381be911bb16224c57ad364dc8e4e85ce74616523360cbf62ab04d84747d3b47b133291c41dbac5e346cc01485dc85f2237f82c17a6612cf5404283d2be5c2e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -18,6 +18,9 @@ module IO::Stream
18
18
  # The maximum read size when appending to IO buffers. Defaults to 8MB.
19
19
  MAXIMUM_READ_SIZE = ENV.fetch("IO_STREAM_MAXIMUM_READ_SIZE", BLOCK_SIZE * 128).to_i
20
20
 
21
+ class LimitError < StandardError
22
+ end
23
+
21
24
  class Generic
22
25
  def initialize(block_size: BLOCK_SIZE, maximum_read_size: MAXIMUM_READ_SIZE)
23
26
  @eof = false
@@ -85,26 +88,37 @@ module IO::Stream
85
88
  read_partial(size) or raise EOFError, "Encountered eof while reading data!"
86
89
  end
87
90
 
88
- # Efficiently read data from the stream until encountering pattern.
89
- # @param pattern [String] The pattern to match.
90
- # @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
91
- def read_until(pattern, offset = 0, chomp: true)
91
+ private def index_of(pattern, offset, limit)
92
92
  # We don't want to split on the pattern, so we subtract the size of the pattern.
93
93
  split_offset = pattern.bytesize - 1
94
-
94
+
95
95
  until index = @read_buffer.index(pattern, offset)
96
96
  offset = @read_buffer.bytesize - split_offset
97
97
 
98
98
  offset = 0 if offset < 0
99
99
 
100
- return unless fill_read_buffer
100
+ return nil if limit and offset >= limit
101
+ return nil unless fill_read_buffer
101
102
  end
102
103
 
103
- @read_buffer.freeze
104
- matched = @read_buffer.byteslice(0, index+(chomp ? 0 : pattern.bytesize))
105
- @read_buffer = @read_buffer.byteslice(index+pattern.bytesize, @read_buffer.bytesize)
106
-
107
- return matched
104
+ return index
105
+ end
106
+
107
+ # Efficiently read data from the stream until encountering pattern.
108
+ # @parameter pattern [String] The pattern to match.
109
+ # @parameter offset [Integer] The offset to start searching from.
110
+ # @parameter limit [Integer] The maximum number of bytes to read, including the pattern (even if chomped).
111
+ # @returns [String | Nil] The contents of the stream up until the pattern, which is consumed but not returned.
112
+ def read_until(pattern, offset = 0, limit: nil, chomp: true)
113
+ if index = index_of(pattern, offset, limit)
114
+ return nil if limit and index >= limit
115
+
116
+ @read_buffer.freeze
117
+ matched = @read_buffer.byteslice(0, index+(chomp ? 0 : pattern.bytesize))
118
+ @read_buffer = @read_buffer.byteslice(index+pattern.bytesize, @read_buffer.bytesize)
119
+
120
+ return matched
121
+ end
108
122
  end
109
123
 
110
124
  def peek(size = nil)
@@ -124,8 +138,45 @@ module IO::Stream
124
138
  return @read_buffer
125
139
  end
126
140
 
127
- def gets(separator = $/, **options)
128
- read_until(separator, **options)
141
+ def gets(separator = $/, limit = nil, chomp: false)
142
+ # Compatibility with IO#gets:
143
+ if separator.is_a?(Integer)
144
+ limit = separator
145
+ separator = $/
146
+ end
147
+
148
+ # We don't want to split in the middle of the separator, so we subtract the size of the separator from the start of the search:
149
+ split_offset = separator.bytesize - 1
150
+
151
+ offset = 0
152
+
153
+ until index = @read_buffer.index(separator, offset)
154
+ offset = @read_buffer.bytesize - split_offset
155
+ offset = 0 if offset < 0
156
+
157
+ # If a limit was given, and the offset is beyond the limit, we should return up to the limit:
158
+ if limit and offset >= limit
159
+ # As we didn't find the separator, there is nothing to chomp either.
160
+ return consume_read_buffer(limit)
161
+ end
162
+
163
+ # If we can't read any more data, we should return what we have:
164
+ return consume_read_buffer unless fill_read_buffer
165
+ end
166
+
167
+ # If the index of the separator was beyond the limit:
168
+ if limit and index >= limit
169
+ # Return up to the limit:
170
+ return consume_read_buffer(limit)
171
+ end
172
+
173
+ # Freeze the read buffer, as this enables us to use byteslice without generating a hidden copy:
174
+ @read_buffer.freeze
175
+
176
+ line = @read_buffer.byteslice(0, index+(chomp ? 0 : separator.bytesize))
177
+ @read_buffer = @read_buffer.byteslice(index+separator.bytesize, @read_buffer.bytesize)
178
+
179
+ return line
129
180
  end
130
181
 
131
182
  private def drain(buffer)
@@ -148,8 +199,8 @@ module IO::Stream
148
199
 
149
200
  # Writes `string` to the buffer. When the buffer is full or #sync is true the
150
201
  # buffer is flushed to the underlying `io`.
151
- # @param string the string to write to the buffer.
152
- # @return the number of bytes appended to the buffer.
202
+ # @parameter string [String] the string to write to the buffer.
203
+ # @returns [Integer] the number of bytes appended to the buffer.
153
204
  def write(string, flush: false)
154
205
  @writing.synchronize do
155
206
  @write_buffer << string
@@ -292,7 +343,7 @@ module IO::Stream
292
343
  end
293
344
 
294
345
  # Consumes at most `size` bytes from the buffer.
295
- # @param size [Integer|nil] The amount of data to consume. If nil, consume entire buffer.
346
+ # @parameter size [Integer|nil] The amount of data to consume. If nil, consume entire buffer.
296
347
  def consume_read_buffer(size = nil)
297
348
  # If we are at eof, and the read buffer is empty, we can't consume anything.
298
349
  return nil if @eof && @read_buffer.empty?
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
6
  module IO::Stream
7
- VERSION = "0.4.3"
7
+ VERSION = "0.6.0"
8
8
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-stream
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -37,7 +37,7 @@ cert_chain:
37
37
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
38
38
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
39
39
  -----END CERTIFICATE-----
40
- date: 2024-10-02 00:00:00.000000000 Z
40
+ date: 2024-10-15 00:00:00.000000000 Z
41
41
  dependencies: []
42
42
  description:
43
43
  email:
metadata.gz.sig CHANGED
@@ -1,3 +1,5 @@
1
- :9�wK+W��t����>��"������*�6Fǟ�*�b8]9�ȳ���KUl��hA<>WXf�ȃ/-�5��N ���^�^
2
- @8A�ډ�^�i��i!M?���jY������7�O�4;ͦ1�Čƴ5��A�+�.H�W��:o4˔}��'�Nk���*��҆�
3
- u�
1
+ �,)Ka�,x}Wjv_���G���ǁ���_C��S��C����k!�h��`Ȕ�A���l�+�� ���X��$��u�����G��ǭ��H���]��N�/�&b$�>C�}ۛfA]���⍣4m��Ⴑvȏ��R�z
2
+ $
3
+ l������G� ����
4
+ ���x޻�|�&7�*V�Q�l�6Z#>y��\�x�E�
5
+ �6��}[Wsc��<������'�vP��O������:N)�Sn�!��2��:�gp�K.@ 7�\�y8yᵚO��\��'��8�^N��/�V�@��k���d0pݵ]��#�Vs%���I(9kX��eO76�