| ... | ... | @@ -17,26 +17,27 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty |
| 17 | 17 | const Self = @This(); |
| 18 | 18 | |
| 19 | 19 | pub fn read(self: *Self, dest: []u8) Error!usize { |
| 20 | | var dest_index: usize = 0; |
| 21 | | |
| 22 | | while (dest_index < dest.len) { |
| 23 | | const written = @min(dest.len - dest_index, self.end - self.start); |
| 24 | | @memcpy(dest[dest_index..][0..written], self.buf[self.start..][0..written]); |
| 25 | | if (written == 0) { |
| 26 | | // buf empty, fill it |
| 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; |
| 20 | // First try reading from the already buffered data onto the destination. |
| 21 | const current = self.buf[self.start..self.end]; |
| 22 | if (current.len != 0) { |
| 23 | const to_transfer = @min(current.len, dest.len); |
| 24 | @memcpy(dest[0..to_transfer], current[0..to_transfer]); |
| 25 | self.start += to_transfer; |
| 26 | return to_transfer; |
| 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 | 43 | pub fn reader(self: *Self) Reader { |
| ... | ... | @@ -134,12 +135,13 @@ test "Block" { |
| 134 | 135 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 135 | 136 | .unbuffered_reader = BlockReader.init(block, 2), |
| 136 | 137 | }; |
| 138 | const reader = test_buf_reader.reader(); |
| 137 | 139 | var out_buf: [4]u8 = undefined; |
| 138 | | _ = try test_buf_reader.read(&out_buf); |
| 140 | _ = try reader.readAll(&out_buf); |
| 139 | 141 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 140 | | _ = try test_buf_reader.read(&out_buf); |
| 142 | _ = try reader.readAll(&out_buf); |
| 141 | 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 | 147 | // len out < block |
| ... | ... | @@ -147,14 +149,15 @@ test "Block" { |
| 147 | 149 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 148 | 150 | .unbuffered_reader = BlockReader.init(block, 2), |
| 149 | 151 | }; |
| 152 | const reader = test_buf_reader.reader(); |
| 150 | 153 | var out_buf: [3]u8 = undefined; |
| 151 | | _ = try test_buf_reader.read(&out_buf); |
| 154 | _ = try reader.readAll(&out_buf); |
| 152 | 155 | try testing.expectEqualSlices(u8, &out_buf, "012"); |
| 153 | | _ = try test_buf_reader.read(&out_buf); |
| 156 | _ = try reader.readAll(&out_buf); |
| 154 | 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 | 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 | 163 | // len out > block |
| ... | ... | @@ -162,12 +165,13 @@ test "Block" { |
| 162 | 165 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 163 | 166 | .unbuffered_reader = BlockReader.init(block, 2), |
| 164 | 167 | }; |
| 168 | const reader = test_buf_reader.reader(); |
| 165 | 169 | var out_buf: [5]u8 = undefined; |
| 166 | | _ = try test_buf_reader.read(&out_buf); |
| 170 | _ = try reader.readAll(&out_buf); |
| 167 | 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 | 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 | 177 | // len out == 0 |
| ... | ... | @@ -175,8 +179,9 @@ test "Block" { |
| 175 | 179 | var test_buf_reader: BufferedReader(4, BlockReader) = .{ |
| 176 | 180 | .unbuffered_reader = BlockReader.init(block, 2), |
| 177 | 181 | }; |
| 182 | const reader = test_buf_reader.reader(); |
| 178 | 183 | var out_buf: [0]u8 = undefined; |
| 179 | | _ = try test_buf_reader.read(&out_buf); |
| 184 | _ = try reader.readAll(&out_buf); |
| 180 | 185 | try testing.expectEqualSlices(u8, &out_buf, ""); |
| 181 | 186 | } |
| 182 | 187 | |
| ... | ... | @@ -185,11 +190,12 @@ test "Block" { |
| 185 | 190 | var test_buf_reader: BufferedReader(5, BlockReader) = .{ |
| 186 | 191 | .unbuffered_reader = BlockReader.init(block, 2), |
| 187 | 192 | }; |
| 193 | const reader = test_buf_reader.reader(); |
| 188 | 194 | var out_buf: [4]u8 = undefined; |
| 189 | | _ = try test_buf_reader.read(&out_buf); |
| 195 | _ = try reader.readAll(&out_buf); |
| 190 | 196 | try testing.expectEqualSlices(u8, &out_buf, block); |
| 191 | | _ = try test_buf_reader.read(&out_buf); |
| 197 | _ = try reader.readAll(&out_buf); |
| 192 | 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 | } |