@@ -30,33 +30,6 @@ public struct RESPParser {
3030
3131 private let allocator = ByteBufferAllocator ( )
3232
33- @inline ( __always)
34- private mutating func decoded( value: RESPValue , yield: Yield ) {
35- if let arrayContext = arrayContext {
36- _ = arrayContext. append ( value: value)
37-
38- if arrayContext. isDone {
39- let v = RESPValue . array ( arrayContext. values)
40-
41- if let parent = arrayContext. parent {
42- self . arrayContext = parent
43- }
44- else {
45- self . arrayContext = nil
46- if cachedParseContext == nil {
47- cachedParseContext = arrayContext
48- arrayContext. values = ContiguousArray ( )
49- arrayContext. values. reserveCapacity ( 16 )
50- }
51- }
52- decoded ( value: v, yield: yield)
53- }
54- }
55- else {
56- yield( value)
57- }
58- }
59-
6033 public mutating func feed( _ buffer: ByteBuffer , yield: Yield ) throws {
6134 try buffer. withUnsafeReadableBytes { bp in
6235 let count = bp. count
@@ -146,11 +119,9 @@ public struct RESPParser {
146119 }
147120 else {
148121 if countValue > 0 {
149- arrayContext =
150- makeArrayParseContext ( arrayContext, countValue)
122+ arrayContexts. append ( ArrayParseContext ( countValue) )
151123 }
152124 else {
153- // push an empty array
154125 decoded ( value: . array( [ ] ) , yield: yield)
155126 }
156127 }
@@ -260,24 +231,30 @@ public struct RESPParser {
260231 }
261232 }
262233
263- // finish up.
264- // TBD: I think this is not necessary anymore
265-
266- if let arrayContext = arrayContext {
267- if arrayContext. isDone {
268- let values = arrayContext. values
269- self . arrayContext = nil
270- yield( . array( values) )
271- }
272- else {
273- // we leave the context around
274- }
275- }
234+ assert ( !( arrayContexts. last? . isDone ?? false ) ,
235+ " array context on stack which is done? \( arrayContexts) " )
276236 }
277237
278238
279239 // MARK: - Parsing
280240
241+ @inline ( __always)
242+ private mutating func decoded( value: RESPValue , yield: Yield ) {
243+ if arrayContexts. isEmpty {
244+ return yield ( value)
245+ }
246+
247+ let idx = arrayContexts. endIndex. advanced ( by: - 1 )
248+ let isDone = arrayContexts [ idx] . append ( value: value)
249+
250+ if isDone {
251+ let v = RESPValue . array ( arrayContexts [ idx] . values)
252+
253+ _ = arrayContexts. popLast ( )
254+ decoded ( value: v, yield: yield)
255+ }
256+ }
257+
281258 private enum ParserState {
282259 case protocolError
283260 case start
@@ -290,53 +267,35 @@ public struct RESPParser {
290267 case telnet
291268 }
292269
293- @inline ( __always)
294- private mutating func makeArrayParseContext( _ parent: ArrayParseContext ? = nil ,
295- _ count: Int ) -> ArrayParseContext
296- {
297- if parent == nil && cachedParseContext != nil {
298- let ctx = cachedParseContext!
299- cachedParseContext = nil
300- ctx. count = count
301- ctx. values. reserveCapacity ( count)
302- return ctx
303- }
304- else {
305- return ArrayParseContext ( parent, count)
306- }
307- }
308- private var cachedParseContext : ArrayParseContext ? = nil
270+ private var arrayContexts = ContiguousArray < ArrayParseContext > ( )
309271
310- final private class ArrayParseContext {
272+ private struct ArrayParseContext {
311273
312- let parent : ArrayParseContext ?
313- var values = ContiguousArray < RESPValue > ( )
314- var count : Int
274+ var values = ContiguousArray < RESPValue > ( )
275+ var expectedCount : Int
315276
316- init ( _ parent : ArrayParseContext ? , _ count : Int ) {
317- self . parent = parent
318- self . count = count
277+ init ( _ expectedCount : Int ) {
278+ self . expectedCount = expectedCount
279+ values . reserveCapacity ( expectedCount + 1 )
319280 }
320281
321- var isDone : Bool { return count <= values. count }
322- var isNested : Bool { return parent != nil }
282+ var isDone : Bool {
283+ @inline ( __always) get { return expectedCount <= values. count }
284+ }
323285
324286 @inline ( __always)
325- func append( value v: RESPValue ) -> Bool {
326- assert ( !isNested || !isDone,
327- " attempt to add to a context which is not TL or done " )
287+ mutating func append( value v: RESPValue ) -> Bool {
288+ assert ( !isDone, " attempt to add to a context which is not TL or done " )
328289 values. append ( v)
329290 return isDone
330291 }
331292 }
332293
333294 private var state = ParserState . start
334- private var overflowSkipNL = false
335295 private var hadMinus = false
336296
337297 private var countValue = 0
298+ private var overflowSkipNL = false
338299 private var overflowBuffer : ByteBuffer ?
339-
340- private var arrayContext : ArrayParseContext ?
341300
342301}
0 commit comments