authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-16 17:12:03-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-23 02:37:11-07:00
logd574875f00db32c40019c69465d450a6a58da67f
treec19f6263bd774f08a28d17666a41495333eb4f89
parent3d61890d2405dc861db1e9e5a334ea6f2415a8f1

Revert "std.http: remove 'done' flag"

This reverts commit 42be972a72c86b32ad8403d082ab42763c6facec. Using a bit to distinguish between headers and trailers is fine. It was just named and documented poorly.

4 files changed, 71 insertions(+), 76 deletions(-)

lib/std/http/Client.zig+9-9
...@@ -649,7 +649,7 @@ pub const Request = struct {...@@ -649,7 +649,7 @@ pub const Request = struct {
649 /// Frees all resources associated with the request.649 /// Frees all resources associated with the request.
650 pub fn deinit(req: *Request) void {650 pub fn deinit(req: *Request) void {
651 if (req.connection) |connection| {651 if (req.connection) |connection| {
652 if (req.response.parser.state != .complete) {652 if (!req.response.parser.done) {
653 // If the response wasn't fully read, then we need to close the connection.653 // If the response wasn't fully read, then we need to close the connection.
654 connection.closing = true;654 connection.closing = true;
655 }655 }
...@@ -664,7 +664,7 @@ pub const Request = struct {...@@ -664,7 +664,7 @@ pub const Request = struct {
664 // or keep those which will be used.664 // or keep those which will be used.
665 // This needs to be kept in sync with deinit and request.665 // This needs to be kept in sync with deinit and request.
666 fn redirect(req: *Request, uri: Uri) !void {666 fn redirect(req: *Request, uri: Uri) !void {
667 assert(req.response.parser.state == .complete);667 assert(req.response.parser.done);
668668
669 req.client.connection_pool.release(req.client.allocator, req.connection.?);669 req.client.connection_pool.release(req.client.allocator, req.connection.?);
670 req.connection = null;670 req.connection = null;
...@@ -823,12 +823,12 @@ pub const Request = struct {...@@ -823,12 +823,12 @@ pub const Request = struct {
823 }823 }
824824
825 fn transferRead(req: *Request, buf: []u8) TransferReadError!usize {825 fn transferRead(req: *Request, buf: []u8) TransferReadError!usize {
826 if (req.response.parser.state == .complete) return 0;826 if (req.response.parser.done) return 0;
827827
828 var index: usize = 0;828 var index: usize = 0;
829 while (index == 0) {829 while (index == 0) {
830 const amt = try req.response.parser.read(req.connection.?, buf[index..], req.response.skip);830 const amt = try req.response.parser.read(req.connection.?, buf[index..], req.response.skip);
831 if (amt == 0 and req.response.parser.state == .complete) break;831 if (amt == 0 and req.response.parser.done) break;
832 index += amt;832 index += amt;
833 }833 }
834834
...@@ -873,7 +873,7 @@ pub const Request = struct {...@@ -873,7 +873,7 @@ pub const Request = struct {
873 if (req.response.status == .@"continue") {873 if (req.response.status == .@"continue") {
874 // We're done parsing the continue response; reset to prepare874 // We're done parsing the continue response; reset to prepare
875 // for the real response.875 // for the real response.
876 req.response.parser.state = .complete;876 req.response.parser.done = true;
877 req.response.parser.reset();877 req.response.parser.reset();
878878
879 if (req.handle_continue)879 if (req.handle_continue)
...@@ -885,7 +885,7 @@ pub const Request = struct {...@@ -885,7 +885,7 @@ pub const Request = struct {
885 // we're switching protocols, so this connection is no longer doing http885 // we're switching protocols, so this connection is no longer doing http
886 if (req.method == .CONNECT and req.response.status.class() == .success) {886 if (req.method == .CONNECT and req.response.status.class() == .success) {
887 connection.closing = false;887 connection.closing = false;
888 req.response.parser.state = .complete;888 req.response.parser.done = true;
889 return; // the connection is not HTTP past this point889 return; // the connection is not HTTP past this point
890 }890 }
891891
...@@ -899,7 +899,7 @@ pub const Request = struct {...@@ -899,7 +899,7 @@ pub const Request = struct {
899 if (req.method == .HEAD or req.response.status.class() == .informational or899 if (req.method == .HEAD or req.response.status.class() == .informational or
900 req.response.status == .no_content or req.response.status == .not_modified)900 req.response.status == .no_content or req.response.status == .not_modified)
901 {901 {
902 req.response.parser.state = .complete;902 req.response.parser.done = true;
903 return; // The response is empty; no further setup or redirection is necessary.903 return; // The response is empty; no further setup or redirection is necessary.
904 }904 }
905905
...@@ -914,7 +914,7 @@ pub const Request = struct {...@@ -914,7 +914,7 @@ pub const Request = struct {
914 } else if (req.response.content_length) |cl| {914 } else if (req.response.content_length) |cl| {
915 req.response.parser.next_chunk_length = cl;915 req.response.parser.next_chunk_length = cl;
916916
917 if (cl == 0) req.response.parser.state = .complete;917 if (cl == 0) req.response.parser.done = true;
918 } else {918 } else {
919 // read until the connection is closed919 // read until the connection is closed
920 req.response.parser.next_chunk_length = std.math.maxInt(u64);920 req.response.parser.next_chunk_length = std.math.maxInt(u64);
...@@ -973,7 +973,7 @@ pub const Request = struct {...@@ -973,7 +973,7 @@ pub const Request = struct {
973 try req.send(.{});973 try req.send(.{});
974 } else {974 } else {
975 req.response.skip = false;975 req.response.skip = false;
976 if (req.response.parser.state != .complete) {976 if (!req.response.parser.done) {
977 switch (req.response.transfer_compression) {977 switch (req.response.transfer_compression) {
978 .identity => req.response.compression = .none,978 .identity => req.response.compression = .none,
979 .compress, .@"x-compress" => return error.CompressionUnsupported,979 .compress, .@"x-compress" => return error.CompressionUnsupported,
lib/std/http/Server.zig+6-6
...@@ -352,7 +352,7 @@ pub const Response = struct {...@@ -352,7 +352,7 @@ pub const Response = struct {
352 return .reset;352 return .reset;
353 }353 }
354354
355 if (res.request.parser.state != .complete) {355 if (!res.request.parser.done) {
356 // If the response wasn't fully read, then we need to close the connection.356 // If the response wasn't fully read, then we need to close the connection.
357 res.connection.closing = true;357 res.connection.closing = true;
358 return .closing;358 return .closing;
...@@ -447,12 +447,12 @@ pub const Response = struct {...@@ -447,12 +447,12 @@ pub const Response = struct {
447 }447 }
448448
449 fn transferRead(res: *Response, buf: []u8) TransferReadError!usize {449 fn transferRead(res: *Response, buf: []u8) TransferReadError!usize {
450 if (res.request.parser.state == .complete) return 0;450 if (res.request.parser.done) return 0;
451451
452 var index: usize = 0;452 var index: usize = 0;
453 while (index == 0) {453 while (index == 0) {
454 const amt = try res.request.parser.read(&res.connection, buf[index..], false);454 const amt = try res.request.parser.read(&res.connection, buf[index..], false);
455 if (amt == 0 and res.request.parser.state == .complete) break;455 if (amt == 0 and res.request.parser.done) break;
456 index += amt;456 index += amt;
457 }457 }
458458
...@@ -502,9 +502,9 @@ pub const Response = struct {...@@ -502,9 +502,9 @@ pub const Response = struct {
502 if (res.request.content_length) |len| {502 if (res.request.content_length) |len| {
503 res.request.parser.next_chunk_length = len;503 res.request.parser.next_chunk_length = len;
504504
505 if (len == 0) res.request.parser.state = .complete;505 if (len == 0) res.request.parser.done = true;
506 } else {506 } else {
507 res.request.parser.state = .complete;507 res.request.parser.done = true;
508 }508 }
509 },509 },
510 .chunked => {510 .chunked => {
...@@ -513,7 +513,7 @@ pub const Response = struct {...@@ -513,7 +513,7 @@ pub const Response = struct {
513 },513 },
514 }514 }
515515
516 if (res.request.parser.state != .complete) {516 if (!res.request.parser.done) {
517 switch (res.request.transfer_compression) {517 switch (res.request.transfer_compression) {
518 .identity => res.request.compression = .none,518 .identity => res.request.compression = .none,
519 .compress, .@"x-compress" => return error.CompressionUnsupported,519 .compress, .@"x-compress" => return error.CompressionUnsupported,
lib/std/http/protocol.zig+55-60
...@@ -7,76 +7,64 @@ const assert = std.debug.assert;...@@ -7,76 +7,64 @@ const assert = std.debug.assert;
7const use_vectors = builtin.zig_backend != .stage2_x86_64;7const use_vectors = builtin.zig_backend != .stage2_x86_64;
88
9pub const State = enum {9pub const State = enum {
10 /// Begin header parsing states.
11 invalid,10 invalid,
11
12 // Begin header and trailer parsing states.
13
12 start,14 start,
13 seen_n,15 seen_n,
14 seen_r,16 seen_r,
15 seen_rn,17 seen_rn,
16 seen_rnr,18 seen_rnr,
17 headers_end,19 finished,
18 /// Begin transfer-encoding: chunked parsing states.20
21 // Begin transfer-encoding: chunked parsing states.
22
19 chunk_head_size,23 chunk_head_size,
20 chunk_head_ext,24 chunk_head_ext,
21 chunk_head_r,25 chunk_head_r,
22 chunk_data,26 chunk_data,
23 chunk_data_suffix,27 chunk_data_suffix,
24 chunk_data_suffix_r,28 chunk_data_suffix_r,
25 /// When the parser has finished parsing a complete message. A message is
26 /// only complete after the entire body has been read and any trailing
27 /// headers have been parsed.
28 complete,
2929
30 /// Returns true if the parser is in a content state (ie. not waiting for more headers).30 /// Returns true if the parser is in a content state (ie. not waiting for more headers).
31 pub fn isContent(self: State) bool {31 pub fn isContent(self: State) bool {
32 return switch (self) {32 return switch (self) {
33 .invalid,33 .invalid, .start, .seen_n, .seen_r, .seen_rn, .seen_rnr => false,
34 .start,34 .finished, .chunk_head_size, .chunk_head_ext, .chunk_head_r, .chunk_data, .chunk_data_suffix, .chunk_data_suffix_r => true,
35 .seen_n,
36 .seen_r,
37 .seen_rn,
38 .seen_rnr,
39 => false,
40
41 .headers_end,
42 .chunk_head_size,
43 .chunk_head_ext,
44 .chunk_head_r,
45 .chunk_data,
46 .chunk_data_suffix,
47 .chunk_data_suffix_r,
48 .complete,
49 => true,
50 };35 };
51 }36 }
52};37};
5338
54pub const HeadersParser = struct {39pub const HeadersParser = struct {
55 state: State,40 state: State = .start,
56 /// A fixed buffer of len `max_header_bytes`.41 /// A fixed buffer of len `max_header_bytes`.
57 /// Pointers into this buffer are not stable until after a message is complete.42 /// Pointers into this buffer are not stable until after a message is complete.
58 header_bytes_buffer: []u8,43 header_bytes_buffer: []u8,
59 header_bytes_len: u32,44 header_bytes_len: u32,
60 next_chunk_length: u64,45 next_chunk_length: u64,
46 /// `false`: headers. `true`: trailers.
47 done: bool,
6148
62 /// Initializes the parser with a provided buffer `buf`.49 /// Initializes the parser with a provided buffer `buf`.
63 pub fn init(buf: []u8) HeadersParser {50 pub fn init(buf: []u8) HeadersParser {
64 return .{51 return .{
65 .state = .start,
66 .header_bytes_buffer = buf,52 .header_bytes_buffer = buf,
67 .header_bytes_len = 0,53 .header_bytes_len = 0,
54 .done = false,
68 .next_chunk_length = 0,55 .next_chunk_length = 0,
69 };56 };
70 }57 }
7158
72 /// Reinitialize the parser.59 /// Reinitialize the parser.
73 /// Asserts the parser is in the `complete` state.60 /// Asserts the parser is in the "done" state.
74 pub fn reset(hp: *HeadersParser) void {61 pub fn reset(hp: *HeadersParser) void {
75 assert(hp.state == .complete);62 assert(hp.done);
76 hp.* = .{63 hp.* = .{
77 .state = .start,64 .state = .start,
78 .header_bytes_buffer = hp.header_bytes_buffer,65 .header_bytes_buffer = hp.header_bytes_buffer,
79 .header_bytes_len = 0,66 .header_bytes_len = 0,
67 .done = false,
80 .next_chunk_length = 0,68 .next_chunk_length = 0,
81 };69 };
82 }70 }
...@@ -101,8 +89,7 @@ pub const HeadersParser = struct {...@@ -101,8 +89,7 @@ pub const HeadersParser = struct {
101 while (true) {89 while (true) {
102 switch (r.state) {90 switch (r.state) {
103 .invalid => unreachable,91 .invalid => unreachable,
104 .complete => unreachable,92 .finished => return index,
105 .headers_end => return index,
106 .start => switch (len - index) {93 .start => switch (len - index) {
107 0 => return index,94 0 => return index,
108 1 => {95 1 => {
...@@ -126,7 +113,7 @@ pub const HeadersParser = struct {...@@ -126,7 +113,7 @@ pub const HeadersParser = struct {
126113
127 switch (b16) {114 switch (b16) {
128 int16("\r\n") => r.state = .seen_rn,115 int16("\r\n") => r.state = .seen_rn,
129 int16("\n\n") => r.state = .headers_end,116 int16("\n\n") => r.state = .finished,
130 else => {},117 else => {},
131 }118 }
132119
...@@ -145,7 +132,7 @@ pub const HeadersParser = struct {...@@ -145,7 +132,7 @@ pub const HeadersParser = struct {
145132
146 switch (b16) {133 switch (b16) {
147 int16("\r\n") => r.state = .seen_rn,134 int16("\r\n") => r.state = .seen_rn,
148 int16("\n\n") => r.state = .headers_end,135 int16("\n\n") => r.state = .finished,
149 else => {},136 else => {},
150 }137 }
151138
...@@ -170,7 +157,7 @@ pub const HeadersParser = struct {...@@ -170,7 +157,7 @@ pub const HeadersParser = struct {
170157
171 switch (b16) {158 switch (b16) {
172 int16("\r\n") => r.state = .seen_rn,159 int16("\r\n") => r.state = .seen_rn,
173 int16("\n\n") => r.state = .headers_end,160 int16("\n\n") => r.state = .finished,
174 else => {},161 else => {},
175 }162 }
176163
...@@ -180,7 +167,7 @@ pub const HeadersParser = struct {...@@ -180,7 +167,7 @@ pub const HeadersParser = struct {
180 }167 }
181168
182 switch (b32) {169 switch (b32) {
183 int32("\r\n\r\n") => r.state = .headers_end,170 int32("\r\n\r\n") => r.state = .finished,
184 else => {},171 else => {},
185 }172 }
186173
...@@ -228,7 +215,7 @@ pub const HeadersParser = struct {...@@ -228,7 +215,7 @@ pub const HeadersParser = struct {
228215
229 switch (b16) {216 switch (b16) {
230 int16("\r\n") => r.state = .seen_rn,217 int16("\r\n") => r.state = .seen_rn,
231 int16("\n\n") => r.state = .headers_end,218 int16("\n\n") => r.state = .finished,
232 else => {},219 else => {},
233 }220 }
234 },221 },
...@@ -245,7 +232,7 @@ pub const HeadersParser = struct {...@@ -245,7 +232,7 @@ pub const HeadersParser = struct {
245232
246 switch (b16) {233 switch (b16) {
247 int16("\r\n") => r.state = .seen_rn,234 int16("\r\n") => r.state = .seen_rn,
248 int16("\n\n") => r.state = .headers_end,235 int16("\n\n") => r.state = .finished,
249 else => {},236 else => {},
250 }237 }
251238
...@@ -262,10 +249,10 @@ pub const HeadersParser = struct {...@@ -262,10 +249,10 @@ pub const HeadersParser = struct {
262 const b16 = intShift(u16, b32);249 const b16 = intShift(u16, b32);
263250
264 if (b32 == int32("\r\n\r\n")) {251 if (b32 == int32("\r\n\r\n")) {
265 r.state = .headers_end;252 r.state = .finished;
266 return index + i + 4;253 return index + i + 4;
267 } else if (b16 == int16("\n\n")) {254 } else if (b16 == int16("\n\n")) {
268 r.state = .headers_end;255 r.state = .finished;
269 return index + i + 2;256 return index + i + 2;
270 }257 }
271 }258 }
...@@ -282,7 +269,7 @@ pub const HeadersParser = struct {...@@ -282,7 +269,7 @@ pub const HeadersParser = struct {
282269
283 switch (b16) {270 switch (b16) {
284 int16("\r\n") => r.state = .seen_rn,271 int16("\r\n") => r.state = .seen_rn,
285 int16("\n\n") => r.state = .headers_end,272 int16("\n\n") => r.state = .finished,
286 else => {},273 else => {},
287 }274 }
288275
...@@ -302,7 +289,7 @@ pub const HeadersParser = struct {...@@ -302,7 +289,7 @@ pub const HeadersParser = struct {
302 0 => return index,289 0 => return index,
303 else => {290 else => {
304 switch (bytes[index]) {291 switch (bytes[index]) {
305 '\n' => r.state = .headers_end,292 '\n' => r.state = .finished,
306 else => r.state = .start,293 else => r.state = .start,
307 }294 }
308295
...@@ -334,7 +321,7 @@ pub const HeadersParser = struct {...@@ -334,7 +321,7 @@ pub const HeadersParser = struct {
334 switch (b16) {321 switch (b16) {
335 int16("\r\n") => r.state = .seen_rn,322 int16("\r\n") => r.state = .seen_rn,
336 int16("\n\r") => r.state = .seen_rnr,323 int16("\n\r") => r.state = .seen_rnr,
337 int16("\n\n") => r.state = .headers_end,324 int16("\n\n") => r.state = .finished,
338 else => {},325 else => {},
339 }326 }
340327
...@@ -353,12 +340,12 @@ pub const HeadersParser = struct {...@@ -353,12 +340,12 @@ pub const HeadersParser = struct {
353340
354 switch (b16) {341 switch (b16) {
355 int16("\r\n") => r.state = .seen_rn,342 int16("\r\n") => r.state = .seen_rn,
356 int16("\n\n") => r.state = .headers_end,343 int16("\n\n") => r.state = .finished,
357 else => {},344 else => {},
358 }345 }
359346
360 switch (b24) {347 switch (b24) {
361 int24("\n\r\n") => r.state = .headers_end,348 int24("\n\r\n") => r.state = .finished,
362 else => {},349 else => {},
363 }350 }
364351
...@@ -388,8 +375,8 @@ pub const HeadersParser = struct {...@@ -388,8 +375,8 @@ pub const HeadersParser = struct {
388 }375 }
389376
390 switch (b16) {377 switch (b16) {
391 int16("\r\n") => r.state = .headers_end,378 int16("\r\n") => r.state = .finished,
392 int16("\n\n") => r.state = .headers_end,379 int16("\n\n") => r.state = .finished,
393 else => {},380 else => {},
394 }381 }
395382
...@@ -401,7 +388,7 @@ pub const HeadersParser = struct {...@@ -401,7 +388,7 @@ pub const HeadersParser = struct {
401 0 => return index,388 0 => return index,
402 else => {389 else => {
403 switch (bytes[index]) {390 switch (bytes[index]) {
404 '\n' => r.state = .headers_end,391 '\n' => r.state = .finished,
405 else => r.state = .start,392 else => r.state = .start,
406 }393 }
407394
...@@ -502,6 +489,13 @@ pub const HeadersParser = struct {...@@ -502,6 +489,13 @@ pub const HeadersParser = struct {
502 return len;489 return len;
503 }490 }
504491
492 /// Returns whether or not the parser has finished parsing a complete
493 /// message. A message is only complete after the entire body has been read
494 /// and any trailing headers have been parsed.
495 pub fn isComplete(r: *HeadersParser) bool {
496 return r.done and r.state == .finished;
497 }
498
505 pub const CheckCompleteHeadError = error{HttpHeadersOversize};499 pub const CheckCompleteHeadError = error{HttpHeadersOversize};
506500
507 /// Pushes `in` into the parser. Returns the number of bytes consumed by501 /// Pushes `in` into the parser. Returns the number of bytes consumed by
...@@ -532,12 +526,13 @@ pub const HeadersParser = struct {...@@ -532,12 +526,13 @@ pub const HeadersParser = struct {
532 /// See `std.http.Client.Connection for an example of `conn`.526 /// See `std.http.Client.Connection for an example of `conn`.
533 pub fn read(r: *HeadersParser, conn: anytype, buffer: []u8, skip: bool) !usize {527 pub fn read(r: *HeadersParser, conn: anytype, buffer: []u8, skip: bool) !usize {
534 assert(r.state.isContent());528 assert(r.state.isContent());
529 if (r.done) return 0;
530
535 var out_index: usize = 0;531 var out_index: usize = 0;
536 while (true) {532 while (true) {
537 switch (r.state) {533 switch (r.state) {
538 .complete => return out_index,
539 .invalid, .start, .seen_n, .seen_r, .seen_rn, .seen_rnr => unreachable,534 .invalid, .start, .seen_n, .seen_r, .seen_rn, .seen_rnr => unreachable,
540 .headers_end => {535 .finished => {
541 const data_avail = r.next_chunk_length;536 const data_avail = r.next_chunk_length;
542537
543 if (skip) {538 if (skip) {
...@@ -547,8 +542,7 @@ pub const HeadersParser = struct {...@@ -547,8 +542,7 @@ pub const HeadersParser = struct {
547 conn.drop(@intCast(nread));542 conn.drop(@intCast(nread));
548 r.next_chunk_length -= nread;543 r.next_chunk_length -= nread;
549544
550 if (r.next_chunk_length == 0 or nread == 0)545 if (r.next_chunk_length == 0 or nread == 0) r.done = true;
551 r.state = .complete;
552546
553 return out_index;547 return out_index;
554 } else if (out_index < buffer.len) {548 } else if (out_index < buffer.len) {
...@@ -558,8 +552,7 @@ pub const HeadersParser = struct {...@@ -558,8 +552,7 @@ pub const HeadersParser = struct {
558 const nread = try conn.read(buffer[0..can_read]);552 const nread = try conn.read(buffer[0..can_read]);
559 r.next_chunk_length -= nread;553 r.next_chunk_length -= nread;
560554
561 if (r.next_chunk_length == 0 or nread == 0)555 if (r.next_chunk_length == 0 or nread == 0) r.done = true;
562 r.state = .complete;
563556
564 return nread;557 return nread;
565 } else {558 } else {
...@@ -576,12 +569,14 @@ pub const HeadersParser = struct {...@@ -576,12 +569,14 @@ pub const HeadersParser = struct {
576 .invalid => return error.HttpChunkInvalid,569 .invalid => return error.HttpChunkInvalid,
577 .chunk_data => if (r.next_chunk_length == 0) {570 .chunk_data => if (r.next_chunk_length == 0) {
578 if (std.mem.eql(u8, conn.peek(), "\r\n")) {571 if (std.mem.eql(u8, conn.peek(), "\r\n")) {
579 r.state = .complete;572 r.state = .finished;
573 r.done = true;
580 } else {574 } else {
581 // The trailer section is formatted identically575 // The trailer section is formatted identically to the header section.
582 // to the header section.
583 r.state = .seen_rn;576 r.state = .seen_rn;
584 }577 }
578 r.done = true;
579
585 return out_index;580 return out_index;
586 },581 },
587 else => return out_index,582 else => return out_index,
...@@ -619,21 +614,21 @@ pub const HeadersParser = struct {...@@ -619,21 +614,21 @@ pub const HeadersParser = struct {
619};614};
620615
621inline fn int16(array: *const [2]u8) u16 {616inline fn int16(array: *const [2]u8) u16 {
622 return @bitCast(array.*);617 return @as(u16, @bitCast(array.*));
623}618}
624619
625inline fn int24(array: *const [3]u8) u24 {620inline fn int24(array: *const [3]u8) u24 {
626 return @bitCast(array.*);621 return @as(u24, @bitCast(array.*));
627}622}
628623
629inline fn int32(array: *const [4]u8) u32 {624inline fn int32(array: *const [4]u8) u32 {
630 return @bitCast(array.*);625 return @as(u32, @bitCast(array.*));
631}626}
632627
633inline fn intShift(comptime T: type, x: anytype) T {628inline fn intShift(comptime T: type, x: anytype) T {
634 switch (@import("builtin").cpu.arch.endian()) {629 switch (@import("builtin").cpu.arch.endian()) {
635 .little => return @truncate(x >> (@bitSizeOf(@TypeOf(x)) - @bitSizeOf(T))),630 .little => return @as(T, @truncate(x >> (@bitSizeOf(@TypeOf(x)) - @bitSizeOf(T)))),
636 .big => return @truncate(x),631 .big => return @as(T, @truncate(x)),
637 }632 }
638}633}
639634
test/standalone/http.zig+1-1
...@@ -673,7 +673,7 @@ pub fn main() !void {...@@ -673,7 +673,7 @@ pub fn main() !void {
673 var req = try client.open(.GET, uri, .{673 var req = try client.open(.GET, uri, .{
674 .server_header_buffer = headers_buf,674 .server_header_buffer = headers_buf,
675 });675 });
676 req.response.parser.state = .complete;676 req.response.parser.done = true;
677 req.connection.?.closing = false;677 req.connection.?.closing = false;
678 requests[i] = req;678 requests[i] = req;
679 }679 }