structstd.fmt.Parser[src]

A stream based parser for format strings.

Allows to implement formatters compatible with std.fmt without replicating the standard library behavior.

Functions

Functionnumber[src]

pub fn number(self: *@This()) ?usize

Parameters

self: *@This()

Source Code

Source code
pub fn number(self: *@This()) ?usize {
    var r: ?usize = null;

    while (self.peek(0)) |code_point| {
        switch (code_point) {
            '0'...'9' => {
                if (r == null) r = 0;
                r.? *= 10;
                r.? += code_point - '0';
            },
            else => break,
        }
        _ = self.iter.nextCodepoint();
    }

    return r;
}

Functionuntil[src]

pub fn until(self: *@This(), ch: u21) []const u8

Parameters

self: *@This()
ch: u21

Source Code

Source code
pub fn until(self: *@This(), ch: u21) []const u8 {
    const start = self.iter.i;
    while (self.peek(0)) |code_point| {
        if (code_point == ch)
            break;
        _ = self.iter.nextCodepoint();
    }
    return self.iter.bytes[start..self.iter.i];
}

Functionchar[src]

pub fn char(self: *@This()) ?u21

Parameters

self: *@This()

Source Code

Source code
pub fn char(self: *@This()) ?u21 {
    if (self.iter.nextCodepoint()) |code_point| {
        return code_point;
    }
    return null;
}

Functionmaybe[src]

pub fn maybe(self: *@This(), val: u21) bool

Parameters

self: *@This()
val: u21

Source Code

Source code
pub fn maybe(self: *@This(), val: u21) bool {
    if (self.peek(0) == val) {
        _ = self.iter.nextCodepoint();
        return true;
    }
    return false;
}

Functionspecifier[src]

pub fn specifier(self: *@This()) !Specifier

Parameters

self: *@This()

Source Code

Source code
pub fn specifier(self: *@This()) !Specifier {
    if (self.maybe('[')) {
        const arg_name = self.until(']');

        if (!self.maybe(']'))
            return @field(anyerror, "Expected closing ]");

        return Specifier{ .named = arg_name };
    }
    if (self.number()) |i|
        return Specifier{ .number = i };

    return Specifier{ .none = {} };
}

Functionpeek[src]

pub fn peek(self: *@This(), n: usize) ?u21

Parameters

self: *@This()
n: usize

Source Code

Source code
pub fn peek(self: *@This(), n: usize) ?u21 {
    const original_i = self.iter.i;
    defer self.iter.i = original_i;

    var i: usize = 0;
    var code_point: ?u21 = null;
    while (i <= n) : (i += 1) {
        code_point = self.iter.nextCodepoint();
        if (code_point == null) return null;
    }
    return code_point;
}

Source Code

Source code
pub const Parser = struct {
    iter: std.unicode.Utf8Iterator,

    // Returns a decimal number or null if the current character is not a
    // digit
    pub fn number(self: *@This()) ?usize {
        var r: ?usize = null;

        while (self.peek(0)) |code_point| {
            switch (code_point) {
                '0'...'9' => {
                    if (r == null) r = 0;
                    r.? *= 10;
                    r.? += code_point - '0';
                },
                else => break,
            }
            _ = self.iter.nextCodepoint();
        }

        return r;
    }

    // Returns a substring of the input starting from the current position
    // and ending where `ch` is found or until the end if not found
    pub fn until(self: *@This(), ch: u21) []const u8 {
        const start = self.iter.i;
        while (self.peek(0)) |code_point| {
            if (code_point == ch)
                break;
            _ = self.iter.nextCodepoint();
        }
        return self.iter.bytes[start..self.iter.i];
    }

    // Returns the character pointed to by the iterator if available, or
    // null otherwise
    pub fn char(self: *@This()) ?u21 {
        if (self.iter.nextCodepoint()) |code_point| {
            return code_point;
        }
        return null;
    }

    // Returns true if the iterator points to an existing character and
    // false otherwise
    pub fn maybe(self: *@This(), val: u21) bool {
        if (self.peek(0) == val) {
            _ = self.iter.nextCodepoint();
            return true;
        }
        return false;
    }

    // Returns a decimal number or null if the current character is not a
    // digit
    pub fn specifier(self: *@This()) !Specifier {
        if (self.maybe('[')) {
            const arg_name = self.until(']');

            if (!self.maybe(']'))
                return @field(anyerror, "Expected closing ]");

            return Specifier{ .named = arg_name };
        }
        if (self.number()) |i|
            return Specifier{ .number = i };

        return Specifier{ .none = {} };
    }

    // Returns the n-th next character or null if that's past the end
    pub fn peek(self: *@This(), n: usize) ?u21 {
        const original_i = self.iter.i;
        defer self.iter.i = original_i;

        var i: usize = 0;
        var code_point: ?u21 = null;
        while (i <= n) : (i += 1) {
            code_point = self.iter.nextCodepoint();
            if (code_point == null) return null;
        }
        return code_point;
    }
}