| ... | @@ -51,7 +51,7 @@ pub fn reader(br: *BufferedReader) Reader { | ... | @@ -51,7 +51,7 @@ pub fn reader(br: *BufferedReader) Reader { |
| 51 | | 51 | |
| 52 | /// Equivalent semantics to `std.io.Reader.VTable.readVec`. | 52 | /// Equivalent semantics to `std.io.Reader.VTable.readVec`. |
| 53 | pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize { | 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 | /// Equivalent semantics to `std.io.Reader.VTable.read`. | 57 | /// Equivalent semantics to `std.io.Reader.VTable.read`. |
| ... | @@ -106,10 +106,55 @@ pub fn readRemaining(br: *BufferedReader, bw: *BufferedWriter) Reader.RwRemainin | ... | @@ -106,10 +106,55 @@ pub fn readRemaining(br: *BufferedReader, bw: *BufferedWriter) Reader.RwRemainin |
| 106 | | 106 | |
| 107 | /// Equivalent to `readVec` but reads at most `limit` bytes. | 107 | /// Equivalent to `readVec` but reads at most `limit` bytes. |
| 108 | pub fn readVecLimit(br: *BufferedReader, data: []const []u8, limit: Reader.Limit) Reader.Error!usize { | 108 | pub fn readVecLimit(br: *BufferedReader, data: []const []u8, limit: Reader.Limit) Reader.Error!usize { |
| 109 | _ = br; | 109 | assert(@intFromEnum(Reader.Limit.unlimited) == std.math.maxInt(usize)); |
| 110 | _ = data; | 110 | var remaining = @intFromEnum(limit); |
| 111 | _ = limit; | 111 | for (data, 0..) |buf, i| { |
| 112 | @panic("TODO"); | 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 | fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize { | 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,44 +189,7 @@ fn passthruDiscard(context: ?*anyopaque, limit: Reader.Limit) Reader.Error!usize |
| 144 | | 189 | |
| 145 | fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize { | 190 | fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize { |
| 146 | const br: *BufferedReader = @alignCast(@ptrCast(context)); | 191 | const br: *BufferedReader = @alignCast(@ptrCast(context)); |
| 147 | var total: usize = 0; | 192 | return readVecLimit(br, data, .unlimited); |
| 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; | | |
| 185 | } | 193 | } |
| 186 | | 194 | |
| 187 | pub fn seekBy(br: *BufferedReader, seek_by: i64) !void { | 195 | pub fn seekBy(br: *BufferedReader, seek_by: i64) !void { |