| ... | @@ -17,26 +17,27 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty | ... | @@ -17,26 +17,27 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty |
| 17 | const Self = @This(); | 17 | const Self = @This(); |
| 18 | | 18 | |
| 19 | pub fn read(self: *Self, dest: []u8) Error!usize { | 19 | pub fn read(self: *Self, dest: []u8) Error!usize { |
| 20 | var dest_index: usize = 0; | 20 | // First try reading from the already buffered data onto the destination. |
| 21 | | 21 | const current = self.buf[self.start..self.end]; |
| 22 | while (dest_index < dest.len) { | 22 | if (current.len != 0) { |
| 23 | const written = @min(dest.len - dest_index, self.end - self.start); | 23 | const to_transfer = @min(current.len, dest.len); |
| 24 | @memcpy(dest[dest_index..][0..written], self.buf[self.start..][0..written]); | 24 | @memcpy(dest[0..to_transfer], current[0..to_transfer]); |
| 25 | if (written == 0) { | 25 | self.start += to_transfer; |
| 26 | // buf empty, fill it | 26 | return to_transfer; |
| 27 | const n = try self.unbuffered_reader.read(self.buf[0..]); | | |
| 28 | if (n == 0) { | | |
| 29 | // reading from the unbuffered stream returned nothing | | |
| 30 | // so we have nothing left to read. | | |
| 31 | return dest_index; | | |
| 32 | } | | |
| 33 | self.start = 0; | | |
| 34 | self.end = n; | | |
| 35 | } | | |
| 36 | self.start += written; | | |
| 37 | dest_index += written; | | |
| 38 | } | 27 | } |
| 39 | return dest.len; | 28 | |
| | 29 | // If dest is large, read from the unbuffered reader directly into the destination. |
| | 30 | if (dest.len >= buffer_size) { |
| | 31 | return self.unbuffered_reader.read(dest); |
| | 32 | } |
| | 33 | |
| | 34 | // If dest is small, read from the unbuffered reader into our own internal buffer, |
| | 35 | // and then transfer to destination. |
| | 36 | self.end = try self.unbuffered_reader.read(&self.buf); |
| | 37 | const to_transfer = @min(self.end, dest.len); |
| | 38 | @memcpy(dest[0..to_transfer], self.buf[0..to_transfer]); |
| | 39 | self.start = to_transfer; |
| | 40 | return to_transfer; |
| 40 | } | 41 | } |
| 41 | | 42 | |
| 42 | pub fn reader(self: *Self) Reader { | 43 | pub fn reader(self: *Self) Reader { |
| ... | @@ -134,12 +135,13 @@ test "Block" { | ... | @@ -134,12 +135,13 @@ test "Block" { |
| 134 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ | 135 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 135 | .unbuffered_reader = BlockReader.init(block, 2), | 136 | .unbuffered_reader = BlockReader.init(block, 2), |
| 136 | }; | 137 | }; |
| | 138 | const reader = test_buf_reader.reader(); |
| 137 | var out_buf: [4]u8 = undefined; | 139 | var out_buf: [4]u8 = undefined; |
| 138 | _ = try test_buf_reader.read(&out_buf); | 140 | _ = try reader.readAll(&out_buf); |
| 139 | try testing.expectEqualSlices(u8, &out_buf, block); | 141 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 140 | _ = try test_buf_reader.read(&out_buf); | 142 | _ = try reader.readAll(&out_buf); |
| 141 | try testing.expectEqualSlices(u8, &out_buf, block); | 143 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 142 | try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); | 144 | try testing.expectEqual(try reader.readAll(&out_buf), 0); |
| 143 | } | 145 | } |
| 144 | | 146 | |
| 145 | // len out < block | 147 | // len out < block |
| ... | @@ -147,14 +149,15 @@ test "Block" { | ... | @@ -147,14 +149,15 @@ test "Block" { |
| 147 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ | 149 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 148 | .unbuffered_reader = BlockReader.init(block, 2), | 150 | .unbuffered_reader = BlockReader.init(block, 2), |
| 149 | }; | 151 | }; |
| | 152 | const reader = test_buf_reader.reader(); |
| 150 | var out_buf: [3]u8 = undefined; | 153 | var out_buf: [3]u8 = undefined; |
| 151 | _ = try test_buf_reader.read(&out_buf); | 154 | _ = try reader.readAll(&out_buf); |
| 152 | try testing.expectEqualSlices(u8, &out_buf, "012"); | 155 | try testing.expectEqualSlices(u8, &out_buf, "012"); |
| 153 | _ = try test_buf_reader.read(&out_buf); | 156 | _ = try reader.readAll(&out_buf); |
| 154 | try testing.expectEqualSlices(u8, &out_buf, "301"); | 157 | try testing.expectEqualSlices(u8, &out_buf, "301"); |
| 155 | const n = try test_buf_reader.read(&out_buf); | 158 | const n = try reader.readAll(&out_buf); |
| 156 | try testing.expectEqualSlices(u8, out_buf[0..n], "23"); | 159 | try testing.expectEqualSlices(u8, out_buf[0..n], "23"); |
| 157 | try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); | 160 | try testing.expectEqual(try reader.readAll(&out_buf), 0); |
| 158 | } | 161 | } |
| 159 | | 162 | |
| 160 | // len out > block | 163 | // len out > block |
| ... | @@ -162,12 +165,13 @@ test "Block" { | ... | @@ -162,12 +165,13 @@ test "Block" { |
| 162 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ | 165 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 163 | .unbuffered_reader = BlockReader.init(block, 2), | 166 | .unbuffered_reader = BlockReader.init(block, 2), |
| 164 | }; | 167 | }; |
| | 168 | const reader = test_buf_reader.reader(); |
| 165 | var out_buf: [5]u8 = undefined; | 169 | var out_buf: [5]u8 = undefined; |
| 166 | _ = try test_buf_reader.read(&out_buf); | 170 | _ = try reader.readAll(&out_buf); |
| 167 | try testing.expectEqualSlices(u8, &out_buf, "01230"); | 171 | try testing.expectEqualSlices(u8, &out_buf, "01230"); |
| 168 | const n = try test_buf_reader.read(&out_buf); | 172 | const n = try reader.readAll(&out_buf); |
| 169 | try testing.expectEqualSlices(u8, out_buf[0..n], "123"); | 173 | try testing.expectEqualSlices(u8, out_buf[0..n], "123"); |
| 170 | try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); | 174 | try testing.expectEqual(try reader.readAll(&out_buf), 0); |
| 171 | } | 175 | } |
| 172 | | 176 | |
| 173 | // len out == 0 | 177 | // len out == 0 |
| ... | @@ -175,8 +179,9 @@ test "Block" { | ... | @@ -175,8 +179,9 @@ test "Block" { |
| 175 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ | 179 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 176 | .unbuffered_reader = BlockReader.init(block, 2), | 180 | .unbuffered_reader = BlockReader.init(block, 2), |
| 177 | }; | 181 | }; |
| | 182 | const reader = test_buf_reader.reader(); |
| 178 | var out_buf: [0]u8 = undefined; | 183 | var out_buf: [0]u8 = undefined; |
| 179 | _ = try test_buf_reader.read(&out_buf); | 184 | _ = try reader.readAll(&out_buf); |
| 180 | try testing.expectEqualSlices(u8, &out_buf, ""); | 185 | try testing.expectEqualSlices(u8, &out_buf, ""); |
| 181 | } | 186 | } |
| 182 | | 187 | |
| ... | @@ -185,11 +190,12 @@ test "Block" { | ... | @@ -185,11 +190,12 @@ test "Block" { |
| 185 | var test_buf_reader: BufferedReader(5, BlockReader) = .{ | 190 | var test_buf_reader: BufferedReader(5, BlockReader) = .{ |
| 186 | .unbuffered_reader = BlockReader.init(block, 2), | 191 | .unbuffered_reader = BlockReader.init(block, 2), |
| 187 | }; | 192 | }; |
| | 193 | const reader = test_buf_reader.reader(); |
| 188 | var out_buf: [4]u8 = undefined; | 194 | var out_buf: [4]u8 = undefined; |
| 189 | _ = try test_buf_reader.read(&out_buf); | 195 | _ = try reader.readAll(&out_buf); |
| 190 | try testing.expectEqualSlices(u8, &out_buf, block); | 196 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 191 | _ = try test_buf_reader.read(&out_buf); | 197 | _ = try reader.readAll(&out_buf); |
| 192 | try testing.expectEqualSlices(u8, &out_buf, block); | 198 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 193 | try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); | 199 | try testing.expectEqual(try reader.readAll(&out_buf), 0); |
| 194 | } | 200 | } |
| 195 | } | 201 | } |