| author | |
| committer | |
| log | 7b0962938859a955fa8e057ef34f4abd925bb1ca |
| tree | 4e9a27685b5512241f62c8283ddd7f0226a4e63d |
| parent | 533049fdd80a4c7bc3098512b4033a60daea745e |
| signature | Commit is signed but in an unrecognized format. |
2 files changed, 88 insertions(+), 36 deletions(-)
lib/std/http/Client.zig+44-18| ... | @@ -254,44 +254,47 @@ pub const BufferedConnection = struct { | ... | @@ -254,44 +254,47 @@ pub const BufferedConnection = struct { |
| 254 | pub const buffer_size = 0x2000; | 254 | pub const buffer_size = 0x2000; |
| 255 | 255 | ||
| 256 | conn: Connection, | 256 | conn: Connection, |
| 257 | buf: [buffer_size]u8 = undefined, | 257 | read_buf: [buffer_size]u8 = undefined, |
| 258 | start: u16 = 0, | 258 | read_start: u16 = 0, |
| 259 | end: u16 = 0, | 259 | read_end: u16 = 0, |
| 260 | |||
| 261 | write_buf: [buffer_size]u8 = undefined, | ||
| 262 | write_end: u16 = 0, | ||
| 260 | 263 | ||
| 261 | pub fn fill(bconn: *BufferedConnection) ReadError!void { | 264 | pub fn fill(bconn: *BufferedConnection) ReadError!void { |
| 262 | if (bconn.end != bconn.start) return; | 265 | if (bconn.read_end != bconn.read_start) return; |
| 263 | 266 | ||
| 264 | const nread = try bconn.conn.read(bconn.buf[0..]); | 267 | const nread = try bconn.conn.read(bconn.read_buf[0..]); |
| 265 | if (nread == 0) return error.EndOfStream; | 268 | if (nread == 0) return error.EndOfStream; |
| 266 | bconn.start = 0; | 269 | bconn.read_start = 0; |
| 267 | bconn.end = @intCast(u16, nread); | 270 | bconn.read_end = @intCast(u16, nread); |
| 268 | } | 271 | } |
| 269 | 272 | ||
| 270 | pub fn peek(bconn: *BufferedConnection) []const u8 { | 273 | pub fn peek(bconn: *BufferedConnection) []const u8 { |
| 271 | return bconn.buf[bconn.start..bconn.end]; | 274 | return bconn.read_buf[bconn.read_start..bconn.read_end]; |
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | pub fn clear(bconn: *BufferedConnection, num: u16) void { | 277 | pub fn clear(bconn: *BufferedConnection, num: u16) void { |
| 275 | bconn.start += num; | 278 | bconn.read_start += num; |
| 276 | } | 279 | } |
| 277 | 280 | ||
| 278 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { | 281 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 279 | var out_index: u16 = 0; | 282 | var out_index: u16 = 0; |
| 280 | while (out_index < len) { | 283 | while (out_index < len) { |
| 281 | const available = bconn.end - bconn.start; | 284 | const available = bconn.read_end - bconn.read_start; |
| 282 | const left = buffer.len - out_index; | 285 | const left = buffer.len - out_index; |
| 283 | 286 | ||
| 284 | if (available > 0) { | 287 | if (available > 0) { |
| 285 | const can_read = @intCast(u16, @min(available, left)); | 288 | const can_read = @intCast(u16, @min(available, left)); |
| 286 | 289 | ||
| 287 | @memcpy(buffer[out_index..][0..can_read], bconn.buf[bconn.start..][0..can_read]); | 290 | @memcpy(buffer[out_index..][0..can_read], bconn.read_buf[bconn.read_start..][0..can_read]); |
| 288 | out_index += can_read; | 291 | out_index += can_read; |
| 289 | bconn.start += can_read; | 292 | bconn.read_start += can_read; |
| 290 | 293 | ||
| 291 | continue; | 294 | continue; |
| 292 | } | 295 | } |
| 293 | 296 | ||
| 294 | if (left > bconn.buf.len) { | 297 | if (left > bconn.read_buf.len) { |
| 295 | // skip the buffer if the output is large enough | 298 | // skip the buffer if the output is large enough |
| 296 | return bconn.conn.read(buffer[out_index..]); | 299 | return bconn.conn.read(buffer[out_index..]); |
| 297 | } | 300 | } |
| ... | @@ -314,11 +317,33 @@ pub const BufferedConnection = struct { | ... | @@ -314,11 +317,33 @@ pub const BufferedConnection = struct { |
| 314 | } | 317 | } |
| 315 | 318 | ||
| 316 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { | 319 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { |
| 317 | return bconn.conn.writeAll(buffer); | 320 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { |
| 321 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | ||
| 322 | bconn.write_end += @intCast(u16, buffer.len); | ||
| 323 | } else { | ||
| 324 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 325 | bconn.write_end = 0; | ||
| 326 | |||
| 327 | try bconn.conn.writeAll(buffer); | ||
| 328 | } | ||
| 318 | } | 329 | } |
| 319 | 330 | ||
| 320 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { | 331 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { |
| 321 | return bconn.conn.write(buffer); | 332 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { |
| 333 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | ||
| 334 | bconn.write_end += @intCast(u16, buffer.len); | ||
| 335 | |||
| 336 | return buffer.len; | ||
| 337 | } else { | ||
| 338 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 339 | bconn.write_end = 0; | ||
| 340 | |||
| 341 | return try bconn.conn.write(buffer); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | pub fn flush(bconn: *BufferedConnection) WriteError!void { | ||
| 346 | return bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 322 | } | 347 | } |
| 323 | 348 | ||
| 324 | pub const WriteError = Connection.WriteError; | 349 | pub const WriteError = Connection.WriteError; |
| ... | @@ -567,8 +592,7 @@ pub const Request = struct { | ... | @@ -567,8 +592,7 @@ pub const Request = struct { |
| 567 | 592 | ||
| 568 | /// Send the request to the server. | 593 | /// Send the request to the server. |
| 569 | pub fn start(req: *Request) StartError!void { | 594 | pub fn start(req: *Request) StartError!void { |
| 570 | var buffered = std.io.bufferedWriter(req.connection.data.buffered.writer()); | 595 | const w = req.connection.data.buffered.writer(); |
| 571 | const w = buffered.writer(); | ||
| 572 | 596 | ||
| 573 | try w.writeAll(@tagName(req.method)); | 597 | try w.writeAll(@tagName(req.method)); |
| 574 | try w.writeByte(' '); | 598 | try w.writeByte(' '); |
| ... | @@ -642,7 +666,7 @@ pub const Request = struct { | ... | @@ -642,7 +666,7 @@ pub const Request = struct { |
| 642 | 666 | ||
| 643 | try w.writeAll("\r\n"); | 667 | try w.writeAll("\r\n"); |
| 644 | 668 | ||
| 645 | try buffered.flush(); | 669 | try req.connection.data.buffered.flush(); |
| 646 | } | 670 | } |
| 647 | 671 | ||
| 648 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; | 672 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; |
| ... | @@ -868,6 +892,8 @@ pub const Request = struct { | ... | @@ -868,6 +892,8 @@ pub const Request = struct { |
| 868 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, | 892 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, |
| 869 | .none => {}, | 893 | .none => {}, |
| 870 | } | 894 | } |
| 895 | |||
| 896 | try req.connection.data.buffered.flush(); | ||
| 871 | } | 897 | } |
| 872 | }; | 898 | }; |
| 873 | 899 |
lib/std/http/Server.zig+44-18| ... | @@ -98,44 +98,47 @@ pub const BufferedConnection = struct { | ... | @@ -98,44 +98,47 @@ pub const BufferedConnection = struct { |
| 98 | pub const buffer_size = 0x2000; | 98 | pub const buffer_size = 0x2000; |
| 99 | 99 | ||
| 100 | conn: Connection, | 100 | conn: Connection, |
| 101 | buf: [buffer_size]u8 = undefined, | 101 | read_buf: [buffer_size]u8 = undefined, |
| 102 | start: u16 = 0, | 102 | read_start: u16 = 0, |
| 103 | end: u16 = 0, | 103 | read_end: u16 = 0, |
| 104 | |||
| 105 | write_buf: [buffer_size]u8 = undefined, | ||
| 106 | write_end: u16 = 0, | ||
| 104 | 107 | ||
| 105 | pub fn fill(bconn: *BufferedConnection) ReadError!void { | 108 | pub fn fill(bconn: *BufferedConnection) ReadError!void { |
| 106 | if (bconn.end != bconn.start) return; | 109 | if (bconn.read_end != bconn.read_start) return; |
| 107 | 110 | ||
| 108 | const nread = try bconn.conn.read(bconn.buf[0..]); | 111 | const nread = try bconn.conn.read(bconn.read_buf[0..]); |
| 109 | if (nread == 0) return error.EndOfStream; | 112 | if (nread == 0) return error.EndOfStream; |
| 110 | bconn.start = 0; | 113 | bconn.read_start = 0; |
| 111 | bconn.end = @intCast(u16, nread); | 114 | bconn.read_end = @intCast(u16, nread); |
| 112 | } | 115 | } |
| 113 | 116 | ||
| 114 | pub fn peek(bconn: *BufferedConnection) []const u8 { | 117 | pub fn peek(bconn: *BufferedConnection) []const u8 { |
| 115 | return bconn.buf[bconn.start..bconn.end]; | 118 | return bconn.read_buf[bconn.read_start..bconn.read_end]; |
| 116 | } | 119 | } |
| 117 | 120 | ||
| 118 | pub fn clear(bconn: *BufferedConnection, num: u16) void { | 121 | pub fn clear(bconn: *BufferedConnection, num: u16) void { |
| 119 | bconn.start += num; | 122 | bconn.read_start += num; |
| 120 | } | 123 | } |
| 121 | 124 | ||
| 122 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { | 125 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 123 | var out_index: u16 = 0; | 126 | var out_index: u16 = 0; |
| 124 | while (out_index < len) { | 127 | while (out_index < len) { |
| 125 | const available = bconn.end - bconn.start; | 128 | const available = bconn.read_end - bconn.read_start; |
| 126 | const left = buffer.len - out_index; | 129 | const left = buffer.len - out_index; |
| 127 | 130 | ||
| 128 | if (available > 0) { | 131 | if (available > 0) { |
| 129 | const can_read = @intCast(u16, @min(available, left)); | 132 | const can_read = @intCast(u16, @min(available, left)); |
| 130 | 133 | ||
| 131 | @memcpy(buffer[out_index..][0..can_read], bconn.buf[bconn.start..][0..can_read]); | 134 | @memcpy(buffer[out_index..][0..can_read], bconn.read_buf[bconn.read_start..][0..can_read]); |
| 132 | out_index += can_read; | 135 | out_index += can_read; |
| 133 | bconn.start += can_read; | 136 | bconn.read_start += can_read; |
| 134 | 137 | ||
| 135 | continue; | 138 | continue; |
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | if (left > bconn.buf.len) { | 141 | if (left > bconn.read_buf.len) { |
| 139 | // skip the buffer if the output is large enough | 142 | // skip the buffer if the output is large enough |
| 140 | return bconn.conn.read(buffer[out_index..]); | 143 | return bconn.conn.read(buffer[out_index..]); |
| 141 | } | 144 | } |
| ... | @@ -158,11 +161,33 @@ pub const BufferedConnection = struct { | ... | @@ -158,11 +161,33 @@ pub const BufferedConnection = struct { |
| 158 | } | 161 | } |
| 159 | 162 | ||
| 160 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { | 163 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { |
| 161 | return bconn.conn.writeAll(buffer); | 164 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { |
| 165 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | ||
| 166 | bconn.write_end += @intCast(u16, buffer.len); | ||
| 167 | } else { | ||
| 168 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 169 | bconn.write_end = 0; | ||
| 170 | |||
| 171 | try bconn.conn.writeAll(buffer); | ||
| 172 | } | ||
| 162 | } | 173 | } |
| 163 | 174 | ||
| 164 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { | 175 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { |
| 165 | return bconn.conn.write(buffer); | 176 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { |
| 177 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | ||
| 178 | bconn.write_end += @intCast(u16, buffer.len); | ||
| 179 | |||
| 180 | return buffer.len; | ||
| 181 | } else { | ||
| 182 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 183 | bconn.write_end = 0; | ||
| 184 | |||
| 185 | return try bconn.conn.write(buffer); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | pub fn flush(bconn: *BufferedConnection) WriteError!void { | ||
| 190 | return bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | ||
| 166 | } | 191 | } |
| 167 | 192 | ||
| 168 | pub const WriteError = Connection.WriteError; | 193 | pub const WriteError = Connection.WriteError; |
| ... | @@ -426,8 +451,7 @@ pub const Response = struct { | ... | @@ -426,8 +451,7 @@ pub const Response = struct { |
| 426 | .first, .start, .responded, .finished => unreachable, | 451 | .first, .start, .responded, .finished => unreachable, |
| 427 | } | 452 | } |
| 428 | 453 | ||
| 429 | var buffered = std.io.bufferedWriter(res.connection.writer()); | 454 | const w = res.connection.writer(); |
| 430 | const w = buffered.writer(); | ||
| 431 | 455 | ||
| 432 | try w.writeAll(@tagName(res.version)); | 456 | try w.writeAll(@tagName(res.version)); |
| 433 | try w.writeByte(' '); | 457 | try w.writeByte(' '); |
| ... | @@ -485,7 +509,7 @@ pub const Response = struct { | ... | @@ -485,7 +509,7 @@ pub const Response = struct { |
| 485 | 509 | ||
| 486 | try w.writeAll("\r\n"); | 510 | try w.writeAll("\r\n"); |
| 487 | 511 | ||
| 488 | try buffered.flush(); | 512 | try res.connection.flush(); |
| 489 | } | 513 | } |
| 490 | 514 | ||
| 491 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; | 515 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; |
| ... | @@ -669,6 +693,8 @@ pub const Response = struct { | ... | @@ -669,6 +693,8 @@ pub const Response = struct { |
| 669 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, | 693 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, |
| 670 | .none => {}, | 694 | .none => {}, |
| 671 | } | 695 | } |
| 696 | |||
| 697 | try res.connection.flush(); | ||
| 672 | } | 698 | } |
| 673 | }; | 699 | }; |
| 674 | 700 |