| ... | ... | @@ -51,7 +51,7 @@ pub fn reader(br: *BufferedReader) Reader { |
| 51 | 51 | |
| 52 | 52 | /// Equivalent semantics to `std.io.Reader.VTable.readVec`. |
| 53 | 53 | pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize { |
| 54 | | return passthruReadVec(br, data); |
| 54 | return readVecLimit(br, data, .unlimited); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | /// Equivalent semantics to `std.io.Reader.VTable.read`. |
| ... | ... | @@ -106,10 +106,55 @@ pub fn readRemaining(br: *BufferedReader, bw: *BufferedWriter) Reader.RwRemainin |
| 106 | 106 | |
| 107 | 107 | /// Equivalent to `readVec` but reads at most `limit` bytes. |
| 108 | 108 | pub fn readVecLimit(br: *BufferedReader, data: []const []u8, limit: Reader.Limit) Reader.Error!usize { |
| 109 | | _ = br; |
| 110 | | _ = data; |
| 111 | | _ = limit; |
| 112 | | @panic("TODO"); |
| 109 | assert(@intFromEnum(Reader.Limit.unlimited) == std.math.maxInt(usize)); |
| 110 | var remaining = @intFromEnum(limit); |
| 111 | for (data, 0..) |buf, i| { |
| 112 | const buffered = br.buffer[br.seek..br.end]; |
| 113 | const copy_len = @min(buffered.len, buf.len, remaining); |
| 114 | @memcpy(buf[0..copy_len], buffered[0..copy_len]); |
| 115 | br.seek += copy_len; |
| 116 | remaining -= copy_len; |
| 117 | if (remaining == 0) break; |
| 118 | if (buf.len - copy_len == 0) continue; |
| 119 | |
| 120 | br.seek = 0; |
| 121 | br.end = 0; |
| 122 | var vecs: [8][]u8 = undefined; // Arbitrarily chosen value. |
| 123 | const available_remaining_buf = buf[copy_len..]; |
| 124 | vecs[0] = available_remaining_buf[0..@min(available_remaining_buf.len, remaining)]; |
| 125 | const vec_start_remaining = remaining; |
| 126 | remaining -= vecs[0].len; |
| 127 | var vecs_i: usize = 1; |
| 128 | var data_i: usize = i + 1; |
| 129 | while (true) { |
| 130 | if (vecs.len - vecs_i == 0) { |
| 131 | const n = try br.unbuffered_reader.readVec(&vecs); |
| 132 | return @intFromEnum(limit) - vec_start_remaining + n; |
| 133 | } |
| 134 | if (remaining == 0 or data.len - data_i == 0) { |
| 135 | vecs[vecs_i] = br.buffer; |
| 136 | vecs_i += 1; |
| 137 | const n = try br.unbuffered_reader.readVec(vecs[0..vecs_i]); |
| 138 | const cutoff = vec_start_remaining - remaining; |
| 139 | if (n > cutoff) { |
| 140 | br.end = n - cutoff; |
| 141 | return @intFromEnum(limit) - remaining; |
| 142 | } else { |
| 143 | return @intFromEnum(limit) - vec_start_remaining + n; |
| 144 | } |
| 145 | } |
| 146 | if (data[data_i].len == 0) { |
| 147 | data_i += 1; |
| 148 | continue; |
| 149 | } |
| 150 | const data_elem = data[data_i]; |
| 151 | vecs[vecs_i] = data_elem[0..@min(data_elem.len, remaining)]; |
| 152 | remaining -= vecs[vecs_i].len; |
| 153 | vecs_i += 1; |
| 154 | data_i += 1; |
| 155 | } |
| 156 | } |
| 157 | return @intFromEnum(limit) - remaining; |
| 113 | 158 | } |
| 114 | 159 | |
| 115 | 160 | fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize { |
| ... | ... | @@ -144,44 +189,7 @@ fn passthruDiscard(context: ?*anyopaque, limit: Reader.Limit) Reader.Error!usize |
| 144 | 189 | |
| 145 | 190 | fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize { |
| 146 | 191 | const br: *BufferedReader = @alignCast(@ptrCast(context)); |
| 147 | | var total: usize = 0; |
| 148 | | for (data, 0..) |buf, i| { |
| 149 | | const buffered = br.buffer[br.seek..br.end]; |
| 150 | | const copy_len = @min(buffered.len, buf.len); |
| 151 | | @memcpy(buf[0..copy_len], buffered[0..copy_len]); |
| 152 | | total += copy_len; |
| 153 | | br.seek += copy_len; |
| 154 | | if (copy_len < buf.len) { |
| 155 | | br.seek = 0; |
| 156 | | br.end = 0; |
| 157 | | var vecs: [8][]u8 = undefined; // Arbitrarily chosen value. |
| 158 | | vecs[0] = buf[copy_len..]; |
| 159 | | const vecs_len: usize = @min(vecs.len, data.len - i); |
| 160 | | var vec_data_len: usize = vecs[0].len; |
| 161 | | for (vecs[1..vecs_len], data[i + 1 ..][0 .. vecs_len - 1]) |*v, d| { |
| 162 | | vec_data_len += d.len; |
| 163 | | v.* = d; |
| 164 | | } |
| 165 | | if (vecs_len < vecs.len) { |
| 166 | | vecs[vecs_len] = br.buffer; |
| 167 | | const n = try br.unbuffered_reader.readVec(vecs[0 .. vecs_len + 1]); |
| 168 | | total += @min(n, vec_data_len); |
| 169 | | br.end = n -| vec_data_len; |
| 170 | | return total; |
| 171 | | } |
| 172 | | if (vecs[vecs.len - 1].len >= br.buffer.len) { |
| 173 | | total += try br.unbuffered_reader.readVec(&vecs); |
| 174 | | return total; |
| 175 | | } |
| 176 | | vec_data_len -= vecs[vecs.len - 1].len; |
| 177 | | vecs[vecs.len - 1] = br.buffer; |
| 178 | | const n = try br.unbuffered_reader.readVec(&vecs); |
| 179 | | total += @min(n, vec_data_len); |
| 180 | | br.end = n -| vec_data_len; |
| 181 | | return total; |
| 182 | | } |
| 183 | | } |
| 184 | | return total; |
| 192 | return readVecLimit(br, data, .unlimited); |
| 185 | 193 | } |
| 186 | 194 | |
| 187 | 195 | pub fn seekBy(br: *BufferedReader, seek_by: i64) !void { |