Source
pub fn parse(comptime bytes: []const u8) Placeholder {
var parser: Parser = .{ .bytes = bytes, .i = 0 };
const arg = parser.specifier() catch |err| @compileError(@errorName(err));
const specifier_arg = parser.until(':');
if (parser.char()) |b| {
if (b != ':') @compileError("expected : or }, found '" ++ &[1]u8{b} ++ "'");
}
// Parse the fill byte, if present.
//
// When the width field is also specified, the fill byte must
// be followed by an alignment specifier, unless it's '0' (zero)
// (in which case it's handled as part of the width specifier).
var fill: ?u8 = if (parser.peek(1)) |b|
switch (b) {
'<', '^', '>' => parser.char(),
else => null,
}
else
null;
// Parse the alignment parameter
const alignment: ?Alignment = if (parser.peek(0)) |b| init: {
switch (b) {
'<', '^', '>' => {
// consume the character
break :init switch (parser.char().?) {
'<' => .left,
'^' => .center,
else => .right,
};
},
else => break :init null,
}
} else null;
// When none of the fill character and the alignment specifier have
// been provided, check whether the width starts with a zero.
if (fill == null and alignment == null) {
fill = if (parser.peek(0) == '0') '0' else null;
}
// Parse the width parameter
const width = parser.specifier() catch |err| @compileError(@errorName(err));
// Skip the dot, if present
if (parser.char()) |b| {
if (b != '.') @compileError("expected . or }, found '" ++ &[1]u8{b} ++ "'");
}
// Parse the precision parameter
const precision = parser.specifier() catch |err| @compileError(@errorName(err));
if (parser.char()) |b| @compileError("extraneous trailing character '" ++ &[1]u8{b} ++ "'");
const specifier_array = specifier_arg[0..specifier_arg.len].*;
return .{
.specifier_arg = &specifier_array,
.fill = fill orelse default_fill_char,
.alignment = alignment orelse default_alignment,
.arg = arg,
.width = width,
.precision = precision,
};
}