Struct konst::parsing::Parser [−][src]
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 theOk
variant. -
rebind_if_ok
: Like anif let Ok
, but also reassigns variables with the value in theOk
variant. -
parse_any
: Parses any of the string literal patterns using a supportedParser
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.
For calling strip_prefix
with multiple alternative matched
string literals,
you can use the parse_any
macro,
example
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]
self,
matched: &[u8]
) -> Result<Self, ParseError<'a>>
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.
For calling strip_suffix
with multiple alternative matched
string literals,
you can use the parse_any
macro.
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]
self,
matched: &[u8]
) -> Result<Self, ParseError<'a>>
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.
For trimming with multiple needle
s, you can use the parse_any
macro,
example
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.
For trimming with multiple needle
s, you can use the parse_any
macro,
example
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
.
For calling find_skip
with multiple alternative ǹeedle
string literals,
you can use the parse_any
macro,
example
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
.
For calling find_skip
with multiple alternative ǹeedle
string literals,
you can use the parse_any
macro,
example
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]
fn clone(&self) -> Parser<'a>
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[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
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,