structstd.fmt.Placeholder[src]

Fields

specifier_arg: []const u8
fill: u21
alignment: Alignment
arg: Specifier
width: Specifier
precision: Specifier

Functions

Functionparse[src]

pub fn parse(comptime str: anytype) Placeholder

Source Code

Source code
pub fn parse(comptime str: anytype) Placeholder {
    const view = std.unicode.Utf8View.initComptime(&str);
    comptime var parser = Parser{
        .iter = view.iterator(),
    };

    // Parse the positional argument number
    const arg = comptime parser.specifier() catch |err|
        @compileError(@errorName(err));

    // Parse the format specifier
    const specifier_arg = comptime parser.until(':');

    // Skip the colon, if present
    if (comptime parser.char()) |ch| {
        if (ch != ':') {
            @compileError("expected : or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
        }
    }

    // Parse the fill character, if present.
    // When the width field is also specified, the fill character 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: ?u21 = comptime if (parser.peek(1)) |ch|
        switch (ch) {
            '<', '^', '>' => parser.char(),
            else => null,
        }
    else
        null;

    // Parse the alignment parameter
    const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: {
        switch (ch) {
            '<', '^', '>' => {
                // 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 = comptime if (parser.peek(0) == '0') '0' else null;
    }

    // Parse the width parameter
    const width = comptime parser.specifier() catch |err|
        @compileError(@errorName(err));

    // Skip the dot, if present
    if (comptime parser.char()) |ch| {
        if (ch != '.') {
            @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
        }
    }

    // Parse the precision parameter
    const precision = comptime parser.specifier() catch |err|
        @compileError(@errorName(err));

    if (comptime parser.char()) |ch| {
        @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
    }

    return Placeholder{
        .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),
        .fill = fill orelse default_fill_char,
        .alignment = alignment orelse default_alignment,
        .arg = arg,
        .width = width,
        .precision = precision,
    };
}

Source Code

Source code
pub const Placeholder = struct {
    specifier_arg: []const u8,
    fill: u21,
    alignment: Alignment,
    arg: Specifier,
    width: Specifier,
    precision: Specifier,

    pub fn parse(comptime str: anytype) Placeholder {
        const view = std.unicode.Utf8View.initComptime(&str);
        comptime var parser = Parser{
            .iter = view.iterator(),
        };

        // Parse the positional argument number
        const arg = comptime parser.specifier() catch |err|
            @compileError(@errorName(err));

        // Parse the format specifier
        const specifier_arg = comptime parser.until(':');

        // Skip the colon, if present
        if (comptime parser.char()) |ch| {
            if (ch != ':') {
                @compileError("expected : or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
            }
        }

        // Parse the fill character, if present.
        // When the width field is also specified, the fill character 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: ?u21 = comptime if (parser.peek(1)) |ch|
            switch (ch) {
                '<', '^', '>' => parser.char(),
                else => null,
            }
        else
            null;

        // Parse the alignment parameter
        const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: {
            switch (ch) {
                '<', '^', '>' => {
                    // 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 = comptime if (parser.peek(0) == '0') '0' else null;
        }

        // Parse the width parameter
        const width = comptime parser.specifier() catch |err|
            @compileError(@errorName(err));

        // Skip the dot, if present
        if (comptime parser.char()) |ch| {
            if (ch != '.') {
                @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
            }
        }

        // Parse the precision parameter
        const precision = comptime parser.specifier() catch |err|
            @compileError(@errorName(err));

        if (comptime parser.char()) |ch| {
            @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'");
        }

        return Placeholder{
            .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),
            .fill = fill orelse default_fill_char,
            .alignment = alignment orelse default_alignment,
            .arg = arg,
            .width = width,
            .precision = precision,
        };
    }
}