mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
std.fmt.format: support base 64 encoding
This commit is contained in:
parent
8464efa5dd
commit
d87b59f5a5
@ -62,10 +62,11 @@ pub const Options = struct {
|
||||
/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.
|
||||
///
|
||||
/// The *specifier* has several options for types:
|
||||
/// - `x` and `X`: output numeric value in hexadecimal notation
|
||||
/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes
|
||||
/// - `s`:
|
||||
/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
|
||||
/// - for slices of u8, print the entire slice as a string without zero-termination
|
||||
/// - `b64`: output string as standard base64
|
||||
/// - `e`: output floating point value in scientific notation
|
||||
/// - `d`: output numeric value in decimal notation
|
||||
/// - `b`: output integer value in binary notation
|
||||
|
||||
@ -41,7 +41,7 @@ pub fn writer(bw: *BufferedWriter) Writer {
|
||||
|
||||
const fixed_vtable: Writer.VTable = .{
|
||||
.writeSplat = fixed_writeSplat,
|
||||
.writeFile = fixed_writeFile,
|
||||
.writeFile = Writer.unimplemented_writeFile,
|
||||
};
|
||||
|
||||
/// Replaces the `BufferedWriter` with a new one that writes to `buffer` and
|
||||
@ -74,6 +74,10 @@ pub fn flush(bw: *BufferedWriter) anyerror!void {
|
||||
bw.end = 0;
|
||||
}
|
||||
|
||||
pub fn unusedCapacitySlice(bw: *const BufferedWriter) []u8 {
|
||||
return bw.buffer[bw.end..];
|
||||
}
|
||||
|
||||
/// The `data` parameter is mutable because this function needs to mutate the
|
||||
/// fields in order to handle partial writes from `Writer.VTable.writev`.
|
||||
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
|
||||
return passthru_writeSplat(bw, data, splat);
|
||||
}
|
||||
|
||||
pub fn writev(bw: *BufferedWriter, data: []const []const u8) anyerror!usize {
|
||||
return passthru_writeSplat(bw, data, 1);
|
||||
}
|
||||
|
||||
fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
|
||||
const bw: *BufferedWriter = @alignCast(@ptrCast(context));
|
||||
const buffer = bw.buffer;
|
||||
@ -523,23 +531,6 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp
|
||||
}
|
||||
}
|
||||
|
||||
fn fixed_writeFile(
|
||||
context: *anyopaque,
|
||||
file: std.fs.File,
|
||||
offset: u64,
|
||||
len: Writer.VTable.FileLen,
|
||||
headers_and_trailers: []const []const u8,
|
||||
headers_len: usize,
|
||||
) anyerror!usize {
|
||||
_ = context;
|
||||
_ = file;
|
||||
_ = offset;
|
||||
_ = len;
|
||||
_ = headers_and_trailers;
|
||||
_ = headers_len;
|
||||
return error.Unimplemented;
|
||||
}
|
||||
|
||||
pub fn alignBuffer(
|
||||
bw: *BufferedWriter,
|
||||
buffer: []const u8,
|
||||
@ -775,19 +766,22 @@ pub fn printValue(
|
||||
},
|
||||
.slice => {
|
||||
if (actual_fmt.len == 0)
|
||||
@compileError("cannot format slice without a specifier (i.e. {s}, {x}, or {any})");
|
||||
@compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");
|
||||
if (max_depth == 0) {
|
||||
return bw.writeAll("{ ... }");
|
||||
}
|
||||
if (ptr_info.child == u8) {
|
||||
if (actual_fmt[0] == 's') {
|
||||
return alignBufferOptions(bw, value, options);
|
||||
} else if (actual_fmt[0] == 'x') {
|
||||
return printHex(bw, value, .lower);
|
||||
} else if (actual_fmt[0] == 'X') {
|
||||
return printHex(bw, value, .upper);
|
||||
}
|
||||
}
|
||||
if (ptr_info.child == u8) switch (actual_fmt.len) {
|
||||
1 => switch (actual_fmt[0]) {
|
||||
's' => return alignBufferOptions(bw, value, options),
|
||||
'x' => return printHex(bw, value, .lower),
|
||||
'X' => return printHex(bw, value, .upper),
|
||||
else => {},
|
||||
},
|
||||
3 => if (actual_fmt[0] == 'b' and actual_fmt[1] == '6' and actual_fmt[2] == '4') {
|
||||
return printBase64(bw, value);
|
||||
},
|
||||
else => {},
|
||||
};
|
||||
try bw.writeAll("{ ");
|
||||
for (value, 0..) |elem, i| {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!void {
|
||||
var chunker = std.mem.window(u8, bytes, 3, 3);
|
||||
var temp: [5]u8 = undefined;
|
||||
while (chunker.next()) |chunk| try bw.writeAll(std.base64.standard.Encoder.encode(&temp, chunk));
|
||||
}
|
||||
|
||||
test "formatValue max_depth" {
|
||||
const Vec2 = struct {
|
||||
const SelfType = @This();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user