struct Parser [src]

A stream based parser for format strings. Allows to implement formatters compatible with std.fmt without replicating the standard library behavior.

Fields

iter: std.unicode.Utf8Iterator

Members

Source

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; } }