| ... | @@ -76,7 +76,7 @@ pub fn flush(bw: *BufferedWriter) anyerror!void { | ... | @@ -76,7 +76,7 @@ pub fn flush(bw: *BufferedWriter) anyerror!void { |
| 76 | | 76 | |
| 77 | /// The `data` parameter is mutable because this function needs to mutate the | 77 | /// The `data` parameter is mutable because this function needs to mutate the |
| 78 | /// fields in order to handle partial writes from `Writer.VTable.writev`. | 78 | /// fields in order to handle partial writes from `Writer.VTable.writev`. |
| 79 | pub fn writevAll(bw: *BufferedWriter, data: []const []const u8) anyerror!void { | 79 | pub fn writevAll(bw: *BufferedWriter, data: [][]const u8) anyerror!void { |
| 80 | var i: usize = 0; | 80 | var i: usize = 0; |
| 81 | while (true) { | 81 | while (true) { |
| 82 | var n = try passthru_writeSplat(bw, data[i..], 1); | 82 | var n = try passthru_writeSplat(bw, data[i..], 1); |
| ... | @@ -164,7 +164,7 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi | ... | @@ -164,7 +164,7 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi |
| 164 | @branchHint(.likely); | 164 | @branchHint(.likely); |
| 165 | @memset(buffer[end..new_end], pattern[0]); | 165 | @memset(buffer[end..new_end], pattern[0]); |
| 166 | bw.end = new_end; | 166 | bw.end = new_end; |
| 167 | return end - start_end; | 167 | return new_end - start_end; |
| 168 | } | 168 | } |
| 169 | buffers[0] = buffer[0..end]; | 169 | buffers[0] = buffer[0..end]; |
| 170 | buffers[1] = pattern; | 170 | buffers[1] = pattern; |
| ... | @@ -186,8 +186,8 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi | ... | @@ -186,8 +186,8 @@ fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usi |
| 186 | while (end < new_end) : (end += pattern.len) { | 186 | while (end < new_end) : (end += pattern.len) { |
| 187 | @memcpy(buffer[end..][0..pattern.len], pattern); | 187 | @memcpy(buffer[end..][0..pattern.len], pattern); |
| 188 | } | 188 | } |
| 189 | bw.end = end; | 189 | bw.end = new_end; |
| 190 | return end - start_end; | 190 | return new_end - start_end; |
| 191 | } | 191 | } |
| 192 | buffers[0] = buffer[0..end]; | 192 | buffers[0] = buffer[0..end]; |
| 193 | buffers[1] = pattern; | 193 | buffers[1] = pattern; |
| ... | @@ -471,32 +471,55 @@ pub const WriteFileOptions = struct { | ... | @@ -471,32 +471,55 @@ pub const WriteFileOptions = struct { |
| 471 | pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void { | 471 | pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void { |
| 472 | const headers_and_trailers = options.headers_and_trailers; | 472 | const headers_and_trailers = options.headers_and_trailers; |
| 473 | const headers = headers_and_trailers[0..options.headers_len]; | 473 | const headers = headers_and_trailers[0..options.headers_len]; |
| 474 | var len = options.len; | 474 | if (options.len == .zero) return writevAll(bw, headers_and_trailers); |
| 475 | var i: usize = 0; | 475 | if (options.len == .entire_file) { |
| 476 | var offset = options.offset; | 476 | // When reading the whole file, we cannot include the trailers in the |
| 477 | if (len == .zero) return writevAll(bw, headers_and_trailers[i..]); | 477 | // call that reads from the file handle, because we have no way to |
| 478 | while (i < headers_and_trailers.len) { | 478 | // determine whether a partial write is past the end of the file or |
| 479 | var n = try writeFile(bw, file, offset, len, headers_and_trailers[i..], headers.len - i); | 479 | // not. |
| 480 | while (i < headers.len and n >= headers[i].len) { | 480 | var i: usize = 0; |
| 481 | n -= headers[i].len; | 481 | var offset = options.offset; |
| 482 | i += 1; | 482 | while (true) { |
| 483 | } | 483 | var n = try writeFile(bw, file, offset, .entire_file, headers[i..], headers.len - i); |
| 484 | if (i < headers.len) { | 484 | while (i < headers.len and n >= headers[i].len) { |
| 485 | headers[i] = headers[i][n..]; | 485 | n -= headers[i].len; |
| 486 | continue; | 486 | i += 1; |
| | 487 | } |
| | 488 | if (i < headers.len) { |
| | 489 | headers[i] = headers[i][n..]; |
| | 490 | continue; |
| | 491 | } |
| | 492 | if (n == 0) break; |
| | 493 | offset += n; |
| 487 | } | 494 | } |
| 488 | if (n >= len.int()) { | 495 | } else { |
| 489 | n -= len.int(); | 496 | var len = options.len.int(); |
| 490 | while (n >= headers_and_trailers[i].len) { | 497 | var i: usize = 0; |
| 491 | n -= headers_and_trailers[i].len; | 498 | var offset = options.offset; |
| | 499 | while (true) { |
| | 500 | var n = try writeFile(bw, file, offset, .init(len), headers_and_trailers[i..], headers.len - i); |
| | 501 | while (i < headers.len and n >= headers[i].len) { |
| | 502 | n -= headers[i].len; |
| 492 | i += 1; | 503 | i += 1; |
| | 504 | } |
| | 505 | if (i < headers.len) { |
| | 506 | headers[i] = headers[i][n..]; |
| | 507 | continue; |
| | 508 | } |
| | 509 | if (n >= len) { |
| | 510 | n -= len; |
| 493 | if (i >= headers_and_trailers.len) return; | 511 | if (i >= headers_and_trailers.len) return; |
| | 512 | while (n >= headers_and_trailers[i].len) { |
| | 513 | n -= headers_and_trailers[i].len; |
| | 514 | i += 1; |
| | 515 | if (i >= headers_and_trailers.len) return; |
| | 516 | } |
| | 517 | headers_and_trailers[i] = headers_and_trailers[i][n..]; |
| | 518 | return writevAll(bw, headers_and_trailers[i..]); |
| 494 | } | 519 | } |
| 495 | headers_and_trailers[i] = headers_and_trailers[i][n..]; | 520 | offset += n; |
| 496 | return writevAll(bw, headers_and_trailers[i..]); | 521 | len -= n; |
| 497 | } | 522 | } |
| 498 | offset += n; | | |
| 499 | len = if (len == .entire_file) .entire_file else .init(len.int() - n); | | |
| 500 | } | 523 | } |
| 501 | } | 524 | } |
| 502 | | 525 | |