Thanks to visit codestin.com
Credit goes to lib.rs

4 releases

0.2.3 Apr 15, 2023
0.2.2 Apr 16, 2021
0.2.1 Apr 16, 2021
0.2.0 Mar 8, 2021

#142 in Parser tooling

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

136 downloads per month
Used in 8 crates (4 directly)

MIT/Apache

43KB
1K SLoC

CI crates.io docs.rs

Byte Parser

A library that provides a functional way to easely parse a string or a slice.

Basic Example

use byte_parser::{StrParser, ParseIterator};

let mut parser = StrParser::new("\
    key: value\n\
    other key: more : value\n\
    also valid\
");

let lines: Vec<(&str, &str)> = parser
    .split_on_byte(b'\n')
    .map_and_collect(|line| {

        let key = line
            .record()
            .consume_while_byte_fn(|&b| b != b':')
            .to_str();

        let has_colon = line.advance().is_some();
        if !has_colon {
            return ("", key.trim_start());
        }

        let value = line
            .record()
            .consume_to_str();

        (key, value.trim_start())
    });

assert_eq!(lines[0], ("key", "value"));
assert_eq!(lines[1], ("other key", "more : value"));
assert_eq!(lines[2], ("", "also valid"));

Example parsing a number

# use std::str::FromStr;
use byte_parser::{StrParser, ParseIterator};

#[derive(Debug, PartialEq)]
pub enum Number {
    Uint(usize),
    Integer(isize),
    Float(f32)
}

impl Number {
    /// # Panics
    /// Panics if invalid utf8 is found.
    /// Or if the digit is to large.
    pub fn from_parser<'s, I>(iter: &mut I) -> Option<Self>
    where I: ParseIterator<'s> {
        let mut iter = iter.record();

        // there could be a leading minus -
        let is_negative = iter
            .next_if(|&b| b == b'-')
            .is_some();

            // consume first digits
        iter
            .while_byte_fn(u8::is_ascii_digit)
            .consume_at_least(1)
                .ok()?;
            
        // there could be a dot
        let has_dot = iter
            .next_if(|&b| b == b'.')
            .is_some();

        if !has_dot {
            let s = iter.to_str();
            let num = match is_negative {
                true => Self::Integer(
                    s.parse().expect("digit to large")
                ),
                false => Self::Uint(
                    s.parse().expect("digit to large")
                )
            };

            return Some(num)
            }

            // consume next digits
        iter.consume_while_byte_fn(u8::is_ascii_digit);

        Some(Self::Float(
            iter.to_str().parse().expect("digit to large")
        ))
    }
}

impl FromStr for Number {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        let mut parser = StrParser::new(s);
            let num = Self::from_parser(&mut parser)
            .ok_or(())?;

        // parser not exhausted
        if parser.advance().is_some() {
            return Err(())
        }

        Ok(num)
    }
}

assert_eq!(Number::Float(1.23), "1.23".parse().unwrap());
assert_eq!(Number::Float(-32.1), "-32.1".parse().unwrap());
assert_eq!(Number::Uint(42), "42".parse().unwrap());
assert_eq!(Number::Integer(-42), "-42".parse().unwrap());
assert!(".42".parse::<Number>().is_err());
assert!("5.42 ".parse::<Number>().is_err());

No runtime deps

Features