@@ -18,44 +18,44 @@ def parse(chunk, &block)
1818 # Takes a String buffer to parse and returns String containing any
1919 # text remaining to parse when more data is available.
2020 def do_parse ( buffer )
21- records = buffer . split ( RS , -1 ) # -1 stops suppression of trailing null fields
22-
23- records . each_with_index do |record , i |
24- # RFC7464 2.1 Multiple consecutive RS octets do not denote empty
25- # sequence elements between them and can be ignored.
26- next if record == ''
27-
28- # Try to decode the record
29- begin
30- value = MultiJson . load ( record )
31- result , remaining = handle_parsed ( record , value , is_last_record : i == records . size - 1 )
32- rescue MultiJson ::ParseError => err
33- result , remaining = handle_err ( record , err , is_last_record : i == records . size - 1 )
34- end
35-
36- return remaining if result . nil?
37- yield result
38- end
21+ # RFC7464 2.1 Multiple consecutive RS octets do not denote empty
22+ # sequence elements between them and can be ignored.
23+ records = buffer . split ( RS ) . reject ( &:empty? )
24+
25+ # Every record except the last is guaranteed to be completed
26+ records [ 0 ...-1 ] . each { |record | yield decode_record ( record ) }
27+
28+ last_result = decode_record ( records . last )
29+
30+ # If we have an incomplete record and run out of valid json early, return it to the buffer
31+ return records . last if !buffer . end_with? ( RS ) && partial_result? ( last_result )
32+ yield last_result
3933
4034 ''
4135 end
4236
43- def handle_parsed ( record , value , is_last_record :)
37+ def decode_record ( record )
38+ value = MultiJson . load ( record )
39+ return JsonSequence ::Result ::MaybeTruncated . new ( value ) if truncated? ( record , value )
40+
41+ JsonSequence ::Result ::Json . new ( value )
42+ rescue MultiJson ::ParseError => e
43+ JsonSequence ::Result ::ParseError . new ( record , e )
44+ end
45+
46+ def truncated? ( record , value )
4447 case value
4548 when Numeric , TrueClass , FalseClass , NilClass
4649 # Check for truncation, if record was parsed but doesn't end in
4750 # whitespace it may be truncated
48- if record !~ /\s $/
49- return is_last_record ? [ nil , record ] : [ JsonSequence :: Result :: MaybeTruncated . new ( value ) , '' ]
50- end
51+ record !~ /\s $/
52+ else
53+ false
5154 end
52-
53- [ JsonSequence ::Result ::Json . new ( value ) , '' ]
5455 end
5556
56- def handle_err ( record , err , is_last_record :)
57- # Last record, might be incomplete, stash for later
58- is_last_record ? [ nil , record ] : [ JsonSequence ::Result ::ParseError . new ( record , err ) , '' ]
57+ def partial_result? ( result )
58+ !result . is_a? ( JsonSequence ::Result ::Json )
5959 end
6060 end
6161end
0 commit comments