@@ -45,13 +45,26 @@ public final class GenericStreamReader : StreamReader {
45
45
public private( set) var currentReadPosition = 0
46
46
47
47
/**
48
- The maximum number of bytes that can be returned by the read methods (when updating read position),
48
+ The maximum total number of bytes that can be returned by the read methods (when updating read position),
49
49
and also the number of bytes that can be read from the underlying stream.
50
50
51
51
Changing this to a greater value will force ``streamHasReachedEOF`` to `false`,
52
52
but next read might reach `EOF` directly regardless.
53
53
54
- Changing this to a lower value will not change ``streamHasReachedEOF`` at all. */
54
+ Changing this to a lower value will not change ``streamHasReachedEOF`` at all.
55
+
56
+ The value sets the _total_ number of bytes allowed to be read.
57
+ Let’s see an example, reading a stream whose content is `11 22 33 44 55 66 77 88 99 00` (10 bytes):
58
+ - Set the limit to `nil` (no limit);
59
+ - Read 5 bytes from the stream -> ok, return `11 22 33 44 55`;
60
+ - Set the limit to 7;
61
+ - Read 3 bytes from the stream (w/o allowing reading less) -> throws notEnoughData;
62
+ - Set the limit to 8;
63
+ - Read 3 bytes from the stream (w/o allowing reading less) -> ok, returns `66 77 88`;
64
+ - Read data up to delimiter `99`, excluding the delimiter, w/o failing if not found
65
+ -> ok, returns an empty Data, _and an empty delimiter_ (the delimiter was not read as it’s past the read limit);
66
+ - Set the limit 9;
67
+ - Read data up to delimiter `99`, excluding the delimiter, w/o failing if not found -> ok, returns empty Data and `99` in the delimiter. */
55
68
public var readSizeLimit : Int ? {
56
69
didSet {
57
70
if readSizeLimit ?? Int . max > oldValue ?? Int . max {
@@ -162,11 +175,13 @@ public final class GenericStreamReader : StreamReader {
162
175
var unmatchedDelimiters = Array ( delimiters. filter { !$0. isEmpty } . enumerated ( ) )
163
176
let ( minDelimiterLength, maxDelimiterLength) = ( unmatchedDelimiters. map ( \. element. count) . min ( ) ?? 0 , unmatchedDelimiters. map ( \. element. count) . max ( ) ?? 0 )
164
177
178
+ let allowedToBeRead = readSizeLimit. flatMap { $0 - currentReadPosition } ?? . max
179
+
165
180
var searchOffset = 0
166
181
repeat {
167
182
assert ( bufferValidLength - searchOffset >= 0 , " INTERNAL LOGIC ERROR " )
168
183
let bufferStart = buffer + bufferStartPos
169
- let bufferSearchData = UnsafeRawBufferPointer ( start: bufferStart + searchOffset, count: bufferValidLength - searchOffset)
184
+ let bufferSearchData = UnsafeRawBufferPointer ( start: bufferStart + searchOffset, count: min ( bufferValidLength - searchOffset, allowedToBeRead ) )
170
185
if let match = matchDelimiters ( inData: bufferSearchData, dataStartOffset: searchOffset, usingMatchingMode: matchingMode, includeDelimiter: includeDelimiter, minDelimiterLength: minDelimiterLength, withUnmatchedDelimiters: & unmatchedDelimiters, bestMatch: & bestMatch) {
171
186
if updateReadPosition {
172
187
bufferStartPos += match. length
@@ -202,13 +217,13 @@ public final class GenericStreamReader : StreamReader {
202
217
}
203
218
204
219
/* No match, no error on no match, we return the whole data. */
205
- let returnedLength = bufferValidLength
220
+ let returnedLength = min ( bufferValidLength, allowedToBeRead )
206
221
let bufferStart = buffer + bufferStartPos
207
222
208
223
if updateReadPosition {
209
- currentReadPosition += bufferValidLength
210
- bufferStartPos += bufferValidLength
211
- bufferValidLength = 0
224
+ bufferStartPos += returnedLength
225
+ bufferValidLength -= returnedLength
226
+ currentReadPosition += returnedLength
212
227
}
213
228
214
229
return try handler ( UnsafeRawBufferPointer ( start: bufferStart, count: returnedLength) , Data ( ) )
0 commit comments