| 1 | import io |
| 2 | import x.json2 as json |
| 3 | |
| 4 | struct ChunkedReader { |
| 5 | data []u8 |
| 6 | chunk_size int |
| 7 | mut: |
| 8 | pos int |
| 9 | } |
| 10 | |
| 11 | fn (mut r ChunkedReader) read(mut buf []u8) !int { |
| 12 | if r.pos >= r.data.len { |
| 13 | return io.Eof{} |
| 14 | } |
| 15 | mut n := r.chunk_size |
| 16 | remaining := r.data.len - r.pos |
| 17 | if n > remaining { |
| 18 | n = remaining |
| 19 | } |
| 20 | if n > buf.len { |
| 21 | n = buf.len |
| 22 | } |
| 23 | read := copy(mut buf[..n], r.data[r.pos..r.pos + n]) |
| 24 | r.pos += read |
| 25 | return read |
| 26 | } |
| 27 | |
| 28 | fn test_public_scanner_iterates_tokens() { |
| 29 | mut scanner := json.new_scanner('{"items":[1,true,null,"x"]}') |
| 30 | mut got := []string{} |
| 31 | for { |
| 32 | token := scanner.next()! |
| 33 | got << '${token.kind}:${token.literal()}' |
| 34 | if token.is_eof() { |
| 35 | break |
| 36 | } |
| 37 | } |
| 38 | assert got == [ |
| 39 | 'lcbr:', |
| 40 | 'str:items', |
| 41 | 'colon:', |
| 42 | 'lsbr:', |
| 43 | 'int:1', |
| 44 | 'comma:', |
| 45 | 'bool:true', |
| 46 | 'comma:', |
| 47 | 'null:null', |
| 48 | 'comma:', |
| 49 | 'str:x', |
| 50 | 'rsbr:', |
| 51 | 'rcbr:', |
| 52 | 'eof:', |
| 53 | ] |
| 54 | } |
| 55 | |
| 56 | fn test_reader_scanner_iterates_tokens() { |
| 57 | mut reader := ChunkedReader{ |
| 58 | data: '[10,true,"chunked",null]'.bytes() |
| 59 | chunk_size: 2 |
| 60 | } |
| 61 | mut scanner := json.new_reader_scanner(reader: reader, buffer_size: 3) |
| 62 | defer { |
| 63 | scanner.free() |
| 64 | } |
| 65 | mut got := []string{} |
| 66 | for { |
| 67 | token := scanner.next()! |
| 68 | got << '${token.kind}:${token.literal()}' |
| 69 | if token.is_eof() { |
| 70 | break |
| 71 | } |
| 72 | } |
| 73 | assert got == [ |
| 74 | 'lsbr:', |
| 75 | 'int:10', |
| 76 | 'comma:', |
| 77 | 'bool:true', |
| 78 | 'comma:', |
| 79 | 'str:chunked', |
| 80 | 'comma:', |
| 81 | 'null:null', |
| 82 | 'rsbr:', |
| 83 | 'eof:', |
| 84 | ] |
| 85 | } |
| 86 | |
| 87 | fn test_reader_scanner_reports_errors() { |
| 88 | mut reader := ChunkedReader{ |
| 89 | data: r'["\z"]'.bytes() |
| 90 | chunk_size: 1 |
| 91 | } |
| 92 | mut scanner := json.new_reader_scanner(reader: reader, buffer_size: 1) |
| 93 | defer { |
| 94 | scanner.free() |
| 95 | } |
| 96 | assert scanner.next()!.kind == .lsbr |
| 97 | scanner.next() or { |
| 98 | assert err.msg().contains('invalid backslash escape') |
| 99 | return |
| 100 | } |
| 101 | assert false |
| 102 | } |
| 103 | |