| 1 | module binary |
| 2 | |
| 3 | import io |
| 4 | |
| 5 | struct ChunkedReader { |
| 6 | data []u8 |
| 7 | chunk int = 1 |
| 8 | mut: |
| 9 | offset int |
| 10 | } |
| 11 | |
| 12 | fn (mut r ChunkedReader) read(mut buf []u8) !int { |
| 13 | if r.offset >= r.data.len { |
| 14 | return io.Eof{} |
| 15 | } |
| 16 | mut n := if r.chunk > 0 && r.chunk < buf.len { r.chunk } else { buf.len } |
| 17 | remaining := r.data.len - r.offset |
| 18 | if remaining < n { |
| 19 | n = remaining |
| 20 | } |
| 21 | copy(mut buf[..n], r.data[r.offset..r.offset + n]) |
| 22 | r.offset += n |
| 23 | return n |
| 24 | } |
| 25 | |
| 26 | struct ChunkedWriter { |
| 27 | chunk int = 1 |
| 28 | mut: |
| 29 | data []u8 |
| 30 | } |
| 31 | |
| 32 | fn (mut w ChunkedWriter) write(buf []u8) !int { |
| 33 | if buf.len == 0 { |
| 34 | return 0 |
| 35 | } |
| 36 | n := if w.chunk > 0 && w.chunk < buf.len { w.chunk } else { buf.len } |
| 37 | w.data << buf[..n] |
| 38 | return n |
| 39 | } |
| 40 | |
| 41 | struct Packet { |
| 42 | flag bool |
| 43 | count u16 |
| 44 | values [2]u32 |
| 45 | sample f32 |
| 46 | trailer [3]u8 |
| 47 | } |
| 48 | |
| 49 | struct UnsupportedPacket { |
| 50 | name string |
| 51 | } |
| 52 | |
| 53 | fn test_stream_write_and_read_struct() { |
| 54 | packet := Packet{ |
| 55 | flag: true |
| 56 | count: 0x1234 |
| 57 | values: [u32(0x11223344), 0x55667788]! |
| 58 | sample: f32(12.5) |
| 59 | trailer: [u8(1), 2, 3]! |
| 60 | } |
| 61 | mut writer := ChunkedWriter{ |
| 62 | chunk: 3 |
| 63 | } |
| 64 | write(mut writer, big_endian, packet)! |
| 65 | assert size(packet) == writer.data.len |
| 66 | |
| 67 | mut reader := ChunkedReader{ |
| 68 | data: writer.data.clone() |
| 69 | chunk: 2 |
| 70 | } |
| 71 | mut decoded := Packet{} |
| 72 | read(mut reader, big_endian, mut decoded)! |
| 73 | assert decoded == packet |
| 74 | } |
| 75 | |
| 76 | fn test_stream_read_and_write_slice() { |
| 77 | values := [u16(0x0102), 0x0304, 0x0506] |
| 78 | mut writer := ChunkedWriter{ |
| 79 | chunk: 2 |
| 80 | } |
| 81 | write(mut writer, little_endian, values)! |
| 82 | assert size(values) == 6 |
| 83 | |
| 84 | mut reader := ChunkedReader{ |
| 85 | data: writer.data.clone() |
| 86 | chunk: 1 |
| 87 | } |
| 88 | mut decoded := []u16{len: values.len} |
| 89 | read(mut reader, little_endian, mut decoded)! |
| 90 | assert decoded == values |
| 91 | } |
| 92 | |
| 93 | fn test_stream_read_and_write_bytes() { |
| 94 | bytes := [u8(9), 8, 7, 6, 5] |
| 95 | mut writer := ChunkedWriter{ |
| 96 | chunk: 4 |
| 97 | } |
| 98 | write(mut writer, little_endian, bytes)! |
| 99 | |
| 100 | mut reader := ChunkedReader{ |
| 101 | data: writer.data.clone() |
| 102 | chunk: 2 |
| 103 | } |
| 104 | mut decoded := []u8{len: bytes.len} |
| 105 | read(mut reader, little_endian, mut decoded)! |
| 106 | assert decoded == bytes |
| 107 | } |
| 108 | |
| 109 | fn test_stream_short_read_returns_eof() { |
| 110 | mut reader := ChunkedReader{ |
| 111 | data: [u8(1), 2] |
| 112 | chunk: 1 |
| 113 | } |
| 114 | mut value := u32(0) |
| 115 | if _ := read(mut reader, little_endian, mut value) { |
| 116 | assert false |
| 117 | } else { |
| 118 | assert err is io.Eof |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | fn test_stream_reports_unsupported_types() { |
| 123 | assert size('hello') == -1 |
| 124 | assert size(UnsupportedPacket{}) == -1 |
| 125 | |
| 126 | mut writer := ChunkedWriter{} |
| 127 | if _ := write(mut writer, little_endian, 'hello') { |
| 128 | assert false |
| 129 | } else { |
| 130 | assert err.msg() == 'binary.write: unsupported type string' |
| 131 | } |
| 132 | } |
| 133 | |