authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-05-01 12:13:33-05:00
committergravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-05-06 21:35:16-05:00
log7b0962938859a955fa8e057ef34f4abd925bb1ca
tree4e9a27685b5512241f62c8283ddd7f0226a4e63d
parent533049fdd80a4c7bc3098512b4033a60daea745e
signaturelock-open Commit is signed but in an unrecognized format.

std.http: buffer writes


2 files changed, 88 insertions(+), 36 deletions(-)

lib/std/http/Client.zig+44-18
......@@ -254,44 +254,47 @@ pub const BufferedConnection = struct {
254254 pub const buffer_size = 0x2000;
255255
256256 conn: Connection,
257 buf: [buffer_size]u8 = undefined,
258 start: u16 = 0,
259 end: u16 = 0,
257 read_buf: [buffer_size]u8 = undefined,
258 read_start: u16 = 0,
259 read_end: u16 = 0,
260
261 write_buf: [buffer_size]u8 = undefined,
262 write_end: u16 = 0,
260263
261264 pub fn fill(bconn: *BufferedConnection) ReadError!void {
262 if (bconn.end != bconn.start) return;
265 if (bconn.read_end != bconn.read_start) return;
263266
264 const nread = try bconn.conn.read(bconn.buf[0..]);
267 const nread = try bconn.conn.read(bconn.read_buf[0..]);
265268 if (nread == 0) return error.EndOfStream;
266 bconn.start = 0;
267 bconn.end = @intCast(u16, nread);
269 bconn.read_start = 0;
270 bconn.read_end = @intCast(u16, nread);
268271 }
269272
270273 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];
272275 }
273276
274277 pub fn clear(bconn: *BufferedConnection, num: u16) void {
275 bconn.start += num;
278 bconn.read_start += num;
276279 }
277280
278281 pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize {
279282 var out_index: u16 = 0;
280283 while (out_index < len) {
281 const available = bconn.end - bconn.start;
284 const available = bconn.read_end - bconn.read_start;
282285 const left = buffer.len - out_index;
283286
284287 if (available > 0) {
285288 const can_read = @intCast(u16, @min(available, left));
286289
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]);
288291 out_index += can_read;
289 bconn.start += can_read;
292 bconn.read_start += can_read;
290293
291294 continue;
292295 }
293296
294 if (left > bconn.buf.len) {
297 if (left > bconn.read_buf.len) {
295298 // skip the buffer if the output is large enough
296299 return bconn.conn.read(buffer[out_index..]);
297300 }
......@@ -314,11 +317,33 @@ pub const BufferedConnection = struct {
314317 }
315318
316319 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 }
318329 }
319330
320331 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]);
322347 }
323348
324349 pub const WriteError = Connection.WriteError;
......@@ -567,8 +592,7 @@ pub const Request = struct {
567592
568593 /// Send the request to the server.
569594 pub fn start(req: *Request) StartError!void {
570 var buffered = std.io.bufferedWriter(req.connection.data.buffered.writer());
571 const w = buffered.writer();
595 const w = req.connection.data.buffered.writer();
572596
573597 try w.writeAll(@tagName(req.method));
574598 try w.writeByte(' ');
......@@ -642,7 +666,7 @@ pub const Request = struct {
642666
643667 try w.writeAll("\r\n");
644668
645 try buffered.flush();
669 try req.connection.data.buffered.flush();
646670 }
647671
648672 pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError;
......@@ -868,6 +892,8 @@ pub const Request = struct {
868892 .content_length => |len| if (len != 0) return error.MessageNotCompleted,
869893 .none => {},
870894 }
895
896 try req.connection.data.buffered.flush();
871897 }
872898};
873899
lib/std/http/Server.zig+44-18
......@@ -98,44 +98,47 @@ pub const BufferedConnection = struct {
9898 pub const buffer_size = 0x2000;
9999
100100 conn: Connection,
101 buf: [buffer_size]u8 = undefined,
102 start: u16 = 0,
103 end: u16 = 0,
101 read_buf: [buffer_size]u8 = undefined,
102 read_start: u16 = 0,
103 read_end: u16 = 0,
104
105 write_buf: [buffer_size]u8 = undefined,
106 write_end: u16 = 0,
104107
105108 pub fn fill(bconn: *BufferedConnection) ReadError!void {
106 if (bconn.end != bconn.start) return;
109 if (bconn.read_end != bconn.read_start) return;
107110
108 const nread = try bconn.conn.read(bconn.buf[0..]);
111 const nread = try bconn.conn.read(bconn.read_buf[0..]);
109112 if (nread == 0) return error.EndOfStream;
110 bconn.start = 0;
111 bconn.end = @intCast(u16, nread);
113 bconn.read_start = 0;
114 bconn.read_end = @intCast(u16, nread);
112115 }
113116
114117 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];
116119 }
117120
118121 pub fn clear(bconn: *BufferedConnection, num: u16) void {
119 bconn.start += num;
122 bconn.read_start += num;
120123 }
121124
122125 pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize {
123126 var out_index: u16 = 0;
124127 while (out_index < len) {
125 const available = bconn.end - bconn.start;
128 const available = bconn.read_end - bconn.read_start;
126129 const left = buffer.len - out_index;
127130
128131 if (available > 0) {
129132 const can_read = @intCast(u16, @min(available, left));
130133
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]);
132135 out_index += can_read;
133 bconn.start += can_read;
136 bconn.read_start += can_read;
134137
135138 continue;
136139 }
137140
138 if (left > bconn.buf.len) {
141 if (left > bconn.read_buf.len) {
139142 // skip the buffer if the output is large enough
140143 return bconn.conn.read(buffer[out_index..]);
141144 }
......@@ -158,11 +161,33 @@ pub const BufferedConnection = struct {
158161 }
159162
160163 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 }
162173 }
163174
164175 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]);
166191 }
167192
168193 pub const WriteError = Connection.WriteError;
......@@ -426,8 +451,7 @@ pub const Response = struct {
426451 .first, .start, .responded, .finished => unreachable,
427452 }
428453
429 var buffered = std.io.bufferedWriter(res.connection.writer());
430 const w = buffered.writer();
454 const w = res.connection.writer();
431455
432456 try w.writeAll(@tagName(res.version));
433457 try w.writeByte(' ');
......@@ -485,7 +509,7 @@ pub const Response = struct {
485509
486510 try w.writeAll("\r\n");
487511
488 try buffered.flush();
512 try res.connection.flush();
489513 }
490514
491515 pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError;
......@@ -669,6 +693,8 @@ pub const Response = struct {
669693 .content_length => |len| if (len != 0) return error.MessageNotCompleted,
670694 .none => {},
671695 }
696
697 try res.connection.flush();
672698 }
673699};
674700