Struct konst::parsing::Parser[][src]

pub struct Parser<'a> { /* fields omitted */ }
This is supported on crate feature parsing only.

For parsing and traversing over byte strings in const contexts.

Mutation

Because konst only requires Rust 1.46.0, in order to mutate a parser you must reassign the parser returned by its methods.
eg: parser = parser.trim_start();

To help make this more ergonomic for Result-returning methods, you can use these macros:

  • try_rebind: Like the ? operator, but also reassigns variables with the value in the Ok variant.

  • rebind_if_ok: Like an if let Ok, but also reassigns variables with the value in the Ok variant.

  • parse_any: Parses any of the string literal patterns using a supported Parser method.

Examples

Parsing a variable-length array

Parses a variable-length array, requires the length to appear before the array.

use konst::{
    parsing::{Parser, ParseValueResult},
    for_range, parse_any, try_rebind, unwrap_ctx,
};

// We need to parse the length into a separate const to use it as the length of the array.
const LEN_AND_PARSER: (usize, Parser<'_>) = {
    let input = "\
        6;
        up, 0, 90, down, left, right,
    ";
     
    let parser = Parser::from_str(input);
    let (len, parser) = unwrap_ctx!(parser.parse_usize());
    (len, unwrap_ctx!(parser.strip_prefix_u8(b';')))
};

const LEN: usize = LEN_AND_PARSER.0;

const ANGLES: [Angle; LEN] = unwrap_ctx!(Angle::parse_array(LEN_AND_PARSER.1)).0;

fn main() {
    assert_eq!(
        ANGLES,
        [Angle::UP, Angle::UP, Angle::RIGHT, Angle::DOWN, Angle::LEFT, Angle::RIGHT]
    );
}



#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct Angle(u16);

impl Angle {
    pub const UP: Self = Self(0);
    pub const RIGHT: Self = Self(90);
    pub const DOWN: Self = Self(180);
    pub const LEFT: Self = Self(270);

    pub const fn new(n: u64) -> Angle {
        Angle((n % 360) as u16)
    }

    // This could take a `const LEN: usize` const parameter in Rust 1.51.0,
    // so that the returned array can be any length.
    const fn parse_array(mut parser: Parser<'_>) -> ParseValueResult<'_, [Angle; LEN]> {
        let mut ret = [Angle::UP; LEN];
         
        for_range!{i in 0..LEN =>
            try_rebind!{(ret[i], parser) = Angle::parse(parser.trim_start())}
             
            parser = parser.trim_start();
            if !parser.is_empty() {
                try_rebind!{parser = parser.strip_prefix_u8(b',')}
            }
        }
        Ok((ret, parser))
    }

    pub const fn parse(mut parser: Parser<'_>) -> ParseValueResult<'_, Angle> {
        // Prefer using the `rebind_if_ok` macro if you don't `return` inside the `if let`,
        // because the `parser` inside this `if let` is a different variable than outside.
        if let Ok((angle, parser)) = parser.parse_u64() {
            return Ok((Self::new(angle), parser))
        }
         
        let angle = parse_any!{parser, strip_prefix;
            "up" => Self::UP,
            "right" => Self::RIGHT,
            "down" => Self::DOWN,
            "left" => Self::LEFT,
            _ => return Err(parser.into_other_error())
        };
        Ok((angle, parser))
    }
}

Implementations

impl<'a> Parser<'a>[src]

pub const fn from_bytes(bytes: &'a [u8]) -> Self[src]

Constructs a Parser from a byte string.

pub const fn from_str(string: &'a str) -> Self[src]

Constructs a Parser from a string.

pub const fn bytes(self) -> &'a [u8][src]

Returns the remaining, unparsed bytes.

pub const fn start_offset(self) -> usize[src]

Gets the byte offset of this parser in the str/byte slice that this was constructed from.

pub const fn end_offset(self) -> usize[src]

Gets the end byte offset of this parser in the str/byte slice that this was constructed from.

pub fn parse_direction(&self) -> ParseDirection[src]

The end the parser was last mutated from.

pub const fn into_error(self, kind: ErrorKind) -> ParseError<'a>[src]

Constructs a ParseError for this point in parsing.

pub const fn into_other_error(self) -> ParseError<'a>[src]

Constructs a ParseError for this point in parsing, with an ErrorKind::Other for the kind of error.

pub const fn advance_to_remainder_from_start(self, to: &'a [u8]) -> Self[src]

Updates the unparsed bytes to to, assuming that self.bytes().ends_with(to) is true.

pub const fn advance_to_remainder_from_end(self, to: &'a [u8]) -> Self[src]

Updates the unparsed bytes to to, assuming that self.bytes().starts_with(to) is true.

pub const fn len(self) -> usize[src]

The amount of unparsed bytes.

pub const fn is_empty(self) -> bool[src]

Whether there are any bytes left to parse.

impl<'a> Parser<'a>[src]

pub const fn parse_u128(self) -> ParseValueResult<'a, u128>[src]

Parses a u128 until a non-digit is reached.

Example

use konst::{Parser, unwrap_ctx};

{
    let parser = Parser::from_str("12345");
    let (num, parser) = unwrap_ctx!(parser.parse_u128());
    assert_eq!(num, 12345);
    assert!(parser.bytes().is_empty());
}
{
    let parser = Parser::from_str("1365;6789");
    let (num, parser) = unwrap_ctx!(parser.parse_u128());
    assert_eq!(num, 1365);
    assert_eq!(parser.bytes(), b";6789");
}

pub const fn parse_i128(self) -> ParseValueResult<'a, i128>[src]

Parses a i128 until a non-digit is reached.

Example

use konst::{Parser, unwrap_ctx};

{
    let parser = Parser::from_str("12345");
    let (num, parser) = unwrap_ctx!(parser.parse_i128());
    assert_eq!(num, 12345);
    assert!(parser.bytes().is_empty());
}
{
    let parser = Parser::from_str("-54321;6789");
    let (num, parser) = unwrap_ctx!(parser.parse_i128());
    assert_eq!(num, -54321);
    assert_eq!(parser.bytes(), b";6789");
}

pub const fn parse_u64(self) -> ParseValueResult<'a, u64>[src]

Parses a u64 until a non-digit is reached.

pub const fn parse_i64(self) -> ParseValueResult<'a, i64>[src]

Parses a i64 until a non-digit is reached.

pub const fn parse_usize(self) -> ParseValueResult<'a, usize>[src]

Parses a usize until a non-digit is reached.

pub const fn parse_isize(self) -> ParseValueResult<'a, isize>[src]

Parses a isize until a non-digit is reached.

impl<'a> Parser<'a>[src]

pub const fn parse_bool(self) -> ParseValueResult<'a, bool>[src]

Parses a bool.

Example

use konst::{Parser, unwrap_ctx};

{
    let parser = Parser::from_str("falsemorestring");
    let (boolean, parser) = unwrap_ctx!(parser.parse_bool());
    assert_eq!(boolean, false);
    assert_eq!(parser.bytes(), "morestring".as_bytes());
}
{
    let parser = Parser::from_str("truefoo");
    let (boolean, parser) = unwrap_ctx!(parser.parse_bool());
    assert_eq!(boolean, true);
    assert_eq!(parser.bytes(), "foo".as_bytes());
}

impl<'a> Parser<'a>[src]

pub const fn next_byte(self) -> ParseValueResult<'a, u8>[src]

Gets the next unparsed byte.

pub const fn skip(self, bytes: usize) -> Self[src]

For skipping the first bytes bytes.

Performance

If the “constant_time_slice” feature is disabled, thich takes linear time to remove the leading elements, proportional to bytes.

If the “constant_time_slice” feature is enabled, it takes constant time to run, but uses a few nightly features.

pub const fn strip_prefix(self, matched: &str) -> Result<Self, ParseError<'a>>[src]

Checks that the parsed bytes start with matched, returning the remainder of the bytes.

Examples

Basic

use konst::{Parser, rebind_if_ok};

let mut parser = Parser::from_str("foo;bar;baz;");

assert!(parser.strip_prefix("aaa").is_err());

rebind_if_ok!{parser = parser.strip_prefix("foo;")}
assert_eq!(parser.bytes(), "bar;baz;".as_bytes());

rebind_if_ok!{parser = parser.strip_prefix("bar;")}
assert_eq!(parser.bytes(), "baz;".as_bytes());

rebind_if_ok!{parser = parser.strip_prefix("baz;")}
assert_eq!(parser.bytes(), "".as_bytes());

Use case

use konst::{Parser, rebind_if_ok};

#[derive(Debug, PartialEq)]
struct Flags {
    foo: bool,
    bar: bool,
}

const fn parse_flags(mut parser: Parser<'_>) -> (Flags, Parser<'_>) {
    let mut flags = Flags{foo: false, bar: false};
    rebind_if_ok!{parser = parser.strip_prefix("foo;") =>
        flags.foo = true;
    }
    rebind_if_ok!{parser = parser.strip_prefix("bar;") =>
        flags.bar = true;
    }
    (flags, parser)
}

const VALUES: &[Flags] = &[
    parse_flags(Parser::from_str("")).0,
    parse_flags(Parser::from_str("foo;")).0,
    parse_flags(Parser::from_str("bar;")).0,
    parse_flags(Parser::from_str("foo;bar;")).0,
];

assert_eq!(VALUES[0], Flags{foo: false, bar: false});
assert_eq!(VALUES[1], Flags{foo: true, bar: false});
assert_eq!(VALUES[2], Flags{foo: false, bar: true});
assert_eq!(VALUES[3], Flags{foo: true, bar: true});

pub const fn strip_prefix_b(
    self,
    matched: &[u8]
) -> Result<Self, ParseError<'a>>
[src]

Equivalent to strip_prefix, but takes a byte slice.

pub const fn strip_prefix_u8(self, matched: u8) -> Result<Self, ParseError<'a>>[src]

Equivalent to strip_prefix, but takes a single byte.

Example

use konst::{Parser, rebind_if_ok};

let mut parser = Parser::from_str("abcde");

assert!(parser.strip_prefix_u8(1).is_err());

rebind_if_ok!{parser = parser.strip_prefix_u8(b'a')}
assert_eq!(parser.bytes(), "bcde".as_bytes());

rebind_if_ok!{parser = parser.strip_prefix_u8(b'b')}
assert_eq!(parser.bytes(), "cde".as_bytes());

rebind_if_ok!{parser = parser.strip_prefix_u8(b'c')}
assert_eq!(parser.bytes(), "de".as_bytes());

pub const fn strip_suffix(self, matched: &str) -> Result<Self, ParseError<'a>>[src]

Checks that the parsed bytes end with matched, returning the remainder of the bytes.

Examples

Basic

use konst::{Parser, rebind_if_ok};

let mut parser = Parser::from_str("foo;bar;baz;");

assert!(parser.strip_suffix("aaa").is_err());

rebind_if_ok!{parser = parser.strip_suffix("baz;")}
assert_eq!(parser.bytes(), "foo;bar;".as_bytes());

rebind_if_ok!{parser = parser.strip_suffix("bar;")}
assert_eq!(parser.bytes(), "foo;".as_bytes());

rebind_if_ok!{parser = parser.strip_suffix("foo;")}
assert_eq!(parser.bytes(), "".as_bytes());

pub const fn strip_suffix_b(
    self,
    matched: &[u8]
) -> Result<Self, ParseError<'a>>
[src]

Equivalent to strip_suffix, but takes a byte slice.

pub const fn strip_suffix_u8(self, matched: u8) -> Result<Self, ParseError<'a>>[src]

Equivalent to strip_suffix, but takes a single byte.

Example

use konst::{Parser, rebind_if_ok};

let mut parser = Parser::from_str("edcba");

assert!(parser.strip_suffix_u8(1).is_err());

rebind_if_ok!{parser = parser.strip_suffix_u8(b'a')}
assert_eq!(parser.bytes(), "edcb".as_bytes());

rebind_if_ok!{parser = parser.strip_suffix_u8(b'b')}
assert_eq!(parser.bytes(), "edc".as_bytes());

rebind_if_ok!{parser = parser.strip_suffix_u8(b'c')}
assert_eq!(parser.bytes(), "ed".as_bytes());

pub const fn trim_start(self) -> Self[src]

Removes whitespace from the start of the parsed bytes.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("    foo\n\t bar");

parser = parser.trim_start();
assert_eq!(parser.bytes(), "foo\n\t bar".as_bytes());

parser = unwrap_ctx!(parser.strip_prefix("foo")).trim_start();
assert_eq!(parser.bytes(), "bar".as_bytes());

pub const fn trim_end(self) -> Self[src]

Removes whitespace from the end of the parsed bytes.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("foo,\n    bar,\n    ");

parser = parser.trim_end();
assert_eq!(parser.bytes(), "foo,\n    bar,".as_bytes());

parser = unwrap_ctx!(parser.strip_suffix("bar,")).trim_end();
assert_eq!(parser.bytes(), "foo,".as_bytes());

pub const fn trim_start_matches(self, needle: &str) -> Self[src]

Repeatedly removes all instances of needle from the start of the parsed bytes.

Example

use konst::Parser;

{
    let mut parser = Parser::from_str("HelloHelloHello world!");
    parser = parser.trim_start_matches("Hello");
    assert_eq!(parser.bytes(), " world!".as_bytes());
}
{
    let mut parser = Parser::from_str("        Hi!");
    parser = parser.trim_start_matches("    ");
    assert_eq!(parser.bytes(), "Hi!".as_bytes());
}
{
    let mut parser = Parser::from_str("------Bye!");
    parser = parser.trim_start_matches("----");
    assert_eq!(parser.bytes(), "--Bye!".as_bytes());
}

pub const fn trim_start_matches_b(self, needle: &[u8]) -> Self[src]

Equivalent to trim_start_matches, but takes a byte slice.

pub const fn trim_start_matches_u8(self, needle: u8) -> Self[src]

Equivalent to trim_start_matches, but takes a single byte.

Example

use konst::Parser;

let mut parser = Parser::from_str("    ----world");

parser = parser.trim_start_matches_u8(b' ');
assert_eq!(parser.bytes(), "----world".as_bytes());

parser = parser.trim_start_matches_u8(b'-');
assert_eq!(parser.bytes(), "world".as_bytes());

parser = parser.trim_start_matches_u8(b'-');
assert_eq!(parser.bytes(), "world".as_bytes());

pub const fn trim_end_matches(self, needle: &str) -> Self[src]

Repeatedly removes all instances of needle from the start of the parsed bytes.

Example

use konst::Parser;

{
    let mut parser = Parser::from_str("Hello world!world!world!");
    parser = parser.trim_end_matches("world!");
    assert_eq!(parser.bytes(), "Hello ".as_bytes());
}
{
    let mut parser = Parser::from_str("Hi!        ");
    parser = parser.trim_end_matches("    ");
    assert_eq!(parser.bytes(), "Hi!".as_bytes());
}
{
    let mut parser = Parser::from_str("Bye!------");
    parser = parser.trim_end_matches("----");
    assert_eq!(parser.bytes(), "Bye!--".as_bytes());
}

pub const fn trim_end_matches_b(self, needle: &[u8]) -> Self[src]

Equivalent to trim_end_matches, but takes a byte slice.

pub const fn trim_end_matches_u8(self, needle: u8) -> Self[src]

Equivalent to trim_end_matches, but takes a single byte.

Example

use konst::Parser;

let mut parser = Parser::from_str("world----    ");

parser = parser.trim_end_matches_u8(b' ');
assert_eq!(parser.bytes(), "world----".as_bytes());

parser = parser.trim_end_matches_u8(b'-');
assert_eq!(parser.bytes(), "world".as_bytes());

parser = parser.trim_end_matches_u8(b'-');
assert_eq!(parser.bytes(), "world".as_bytes());

pub const fn find_skip(self, needle: &str) -> Result<Self, ParseError<'a>>[src]

Skips the parser after the first instance of needle.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("foo--bar,baz--qux");

parser = unwrap_ctx!(parser.find_skip("--"));
assert_eq!(parser.bytes(), "bar,baz--qux".as_bytes());

parser = unwrap_ctx!(parser.find_skip("bar,"));
assert_eq!(parser.bytes(), "baz--qux".as_bytes());

parser = unwrap_ctx!(parser.find_skip("--"));
assert_eq!(parser.bytes(), "qux".as_bytes());

assert!(parser.find_skip("--").is_err());

pub const fn find_skip_b(self, needle: &[u8]) -> Result<Self, ParseError<'a>>[src]

Equivalent to find_skip, but takes a byte slice.

pub const fn find_skip_u8(self, needle: u8) -> Result<Self, ParseError<'a>>[src]

Equivalent to find_skip, but takes a single byte.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("foo-bar,baz");

parser = unwrap_ctx!(parser.find_skip_u8(b'-'));
assert_eq!(parser.bytes(), "bar,baz".as_bytes());

parser = unwrap_ctx!(parser.find_skip_u8(b','));
assert_eq!(parser.bytes(), "baz".as_bytes());

pub const fn rfind_skip(self, needle: &str) -> Result<Self, ParseError<'a>>[src]

Truncates the parsed bytes to before the last instance of needle.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("foo--bar,baz--qux");

parser = unwrap_ctx!(parser.rfind_skip("--"));
assert_eq!(parser.bytes(), "foo--bar,baz".as_bytes());

parser = unwrap_ctx!(parser.rfind_skip(",baz"));
assert_eq!(parser.bytes(), "foo--bar".as_bytes());

parser = unwrap_ctx!(parser.rfind_skip("--"));
assert_eq!(parser.bytes(), "foo".as_bytes());

assert!(parser.rfind_skip("--").is_err());

pub const fn rfind_skip_b(self, needle: &[u8]) -> Result<Self, ParseError<'a>>[src]

Equivalent to find_skip, but takes a byte slice.

pub const fn rfind_skip_u8(self, needle: u8) -> Result<Self, ParseError<'a>>[src]

Equivalent to find_skip, but takes a single byte.

Example

use konst::{Parser, unwrap_ctx};

let mut parser = Parser::from_str("foo,bar-baz");

parser = unwrap_ctx!(parser.rfind_skip_u8(b'-'));
assert_eq!(parser.bytes(), "foo,bar".as_bytes());

parser = unwrap_ctx!(parser.rfind_skip_u8(b','));
assert_eq!(parser.bytes(), "foo".as_bytes());

Trait Implementations

impl<'a> Clone for Parser<'a>[src]

impl<'a> Copy for Parser<'a>[src]

impl<'a> Debug for Parser<'a>[src]

impl<'a> Eq for Parser<'a>[src]

impl<'a> PartialEq<Parser<'a>> for Parser<'a>[src]

impl<'a> StructuralEq for Parser<'a>[src]

impl<'a> StructuralPartialEq for Parser<'a>[src]

Auto Trait Implementations

impl<'a> Send for Parser<'a>

impl<'a> Sync for Parser<'a>

impl<'a> Unpin for Parser<'a>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.