| ... | ... | @@ -41,7 +41,7 @@ pub fn writer(bw: *BufferedWriter) Writer { |
| 41 | 41 | |
| 42 | 42 | const fixed_vtable: Writer.VTable = .{ |
| 43 | 43 | .writeSplat = fixed_writeSplat, |
| 44 | | .writeFile = fixed_writeFile, |
| 44 | .writeFile = Writer.unimplemented_writeFile, |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | 47 | /// Replaces the `BufferedWriter` with a new one that writes to `buffer` and |
| ... | ... | @@ -74,6 +74,10 @@ pub fn flush(bw: *BufferedWriter) anyerror!void { |
| 74 | 74 | bw.end = 0; |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | pub fn unusedCapacitySlice(bw: *const BufferedWriter) []u8 { |
| 78 | return bw.buffer[bw.end..]; |
| 79 | } |
| 80 | |
| 77 | 81 | /// The `data` parameter is mutable because this function needs to mutate the |
| 78 | 82 | /// fields in order to handle partial writes from `Writer.VTable.writev`. |
| 79 | 83 | pub fn writevAll(bw: *BufferedWriter, data: [][]const u8) anyerror!void { |
| ... | ... | @@ -93,6 +97,10 @@ pub fn writeSplat(bw: *BufferedWriter, data: []const []const u8, splat: usize) a |
| 93 | 97 | return passthru_writeSplat(bw, data, splat); |
| 94 | 98 | } |
| 95 | 99 | |
| 100 | pub fn writev(bw: *BufferedWriter, data: []const []const u8) anyerror!usize { |
| 101 | return passthru_writeSplat(bw, data, 1); |
| 102 | } |
| 103 | |
| 96 | 104 | fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize { |
| 97 | 105 | const bw: *BufferedWriter = @alignCast(@ptrCast(context)); |
| 98 | 106 | const buffer = bw.buffer; |
| ... | ... | @@ -523,23 +531,6 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp |
| 523 | 531 | } |
| 524 | 532 | } |
| 525 | 533 | |
| 526 | | fn fixed_writeFile( |
| 527 | | context: *anyopaque, |
| 528 | | file: std.fs.File, |
| 529 | | offset: u64, |
| 530 | | len: Writer.VTable.FileLen, |
| 531 | | headers_and_trailers: []const []const u8, |
| 532 | | headers_len: usize, |
| 533 | | ) anyerror!usize { |
| 534 | | _ = context; |
| 535 | | _ = file; |
| 536 | | _ = offset; |
| 537 | | _ = len; |
| 538 | | _ = headers_and_trailers; |
| 539 | | _ = headers_len; |
| 540 | | return error.Unimplemented; |
| 541 | | } |
| 542 | | |
| 543 | 534 | pub fn alignBuffer( |
| 544 | 535 | bw: *BufferedWriter, |
| 545 | 536 | buffer: []const u8, |
| ... | ... | @@ -775,19 +766,22 @@ pub fn printValue( |
| 775 | 766 | }, |
| 776 | 767 | .slice => { |
| 777 | 768 | if (actual_fmt.len == 0) |
| 778 | | @compileError("cannot format slice without a specifier (i.e. {s}, {x}, or {any})"); |
| 769 | @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})"); |
| 779 | 770 | if (max_depth == 0) { |
| 780 | 771 | return bw.writeAll("{ ... }"); |
| 781 | 772 | } |
| 782 | | if (ptr_info.child == u8) { |
| 783 | | if (actual_fmt[0] == 's') { |
| 784 | | return alignBufferOptions(bw, value, options); |
| 785 | | } else if (actual_fmt[0] == 'x') { |
| 786 | | return printHex(bw, value, .lower); |
| 787 | | } else if (actual_fmt[0] == 'X') { |
| 788 | | return printHex(bw, value, .upper); |
| 789 | | } |
| 790 | | } |
| 773 | if (ptr_info.child == u8) switch (actual_fmt.len) { |
| 774 | 1 => switch (actual_fmt[0]) { |
| 775 | 's' => return alignBufferOptions(bw, value, options), |
| 776 | 'x' => return printHex(bw, value, .lower), |
| 777 | 'X' => return printHex(bw, value, .upper), |
| 778 | else => {}, |
| 779 | }, |
| 780 | 3 => if (actual_fmt[0] == 'b' and actual_fmt[1] == '6' and actual_fmt[2] == '4') { |
| 781 | return printBase64(bw, value); |
| 782 | }, |
| 783 | else => {}, |
| 784 | }; |
| 791 | 785 | try bw.writeAll("{ "); |
| 792 | 786 | for (value, 0..) |elem, i| { |
| 793 | 787 | try printValue(bw, actual_fmt, options, elem, max_depth - 1); |
| ... | ... | @@ -1289,6 +1283,12 @@ pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anye |
| 1289 | 1283 | } |
| 1290 | 1284 | } |
| 1291 | 1285 | |
| 1286 | pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!void { |
| 1287 | var chunker = std.mem.window(u8, bytes, 3, 3); |
| 1288 | var temp: [5]u8 = undefined; |
| 1289 | while (chunker.next()) |chunk| try bw.writeAll(std.base64.standard.Encoder.encode(&temp, chunk)); |
| 1290 | } |
| 1291 | |
| 1292 | 1292 | test "formatValue max_depth" { |
| 1293 | 1293 | const Vec2 = struct { |
| 1294 | 1294 | const SelfType = @This(); |