Expand description
This crate provides utilites for parsing byte slices. The API borrows some concepts from other parser-combinator crates but heavily simplifies things by eschewing error management and focusing exclusively on parsing byte slices.
§Overview
The core of the crate is the Pattern
trait. Patterns can be combined using combinatorial
logic to express more complex rules about what a byte (or sequence of bytes) should look like.
The other part of the crate is the Parser
struct. It provides a simpler way to parse a
slice of bytes by continuously matching patterns against it.
§Examples
HTTP request line
Say you want to parse the request line of an HTTP message. There are three important parts to extract: the method, the request target and the protocol version.
GET /hello?value=world HTTP/1.1\r\n
Here is how you would do it:
Note: The rules for parsing http are a bit more nuanced than this
use bparse::{Pattern, Parser};
// This input would probably come from a TcpStream
let input = b"GET /hello?value=world HTTP/1.1\r\n";
let mut parser = Parser::new(input);
// A method is an alphabetic string with at least one character
let method_pattern = bparse::range(b'a', b'z')
.or(bparse::range(b'A', b'Z'))
.repeats(1..);
// A request url must start with a `/` and contains a mix of alphabetic and special characters
let request_target_pattern = "/"
.and(
bparse::range(b'a', b'z')
.or(bparse::range(b'A', b'Z'))
.or(bparse::oneof("?=/"))
.repeats(0..)
);
// We want to match the version exactly
let version_pattern = "HTTP/1.1";
let method = parser.try_match(method_pattern)?;
parser.try_match(" ")?;
let request_target = parser.try_match(request_target_pattern)?;
parser.try_match(" ")?;
let version = parser.try_match(version_pattern)?;
parser.try_match("\r\n".and(bparse::end))?;
assert_eq!(method, b"GET");
assert_eq!(request_target, b"/hello?value=world");
assert_eq!(version, b"HTTP/1.1");
Hexadecimal color parser:
use bparse::{Pattern, Parser, range, end};
use std::str::from_utf8;
#[derive(Debug, PartialEq)]
pub struct Color {
pub red: u8,
pub green: u8,
pub blue: u8,
}
fn main() {
assert_eq!(hex_color("#2F14DF"), Some(Color {
red: 47,
green: 20,
blue: 223,
}));
}
fn hex_color(input: &str) -> Option<Color> {
let hexbyte = range(b'0', b'9').or(range(b'A', b'F')).or(range(b'a', b'f')).repeats(2);
let mut parser = Parser::new(input.as_bytes());
parser.try_match("#")?;
let red = parser.try_match(hexbyte)?;
let green = parser.try_match(hexbyte)?;
let blue = parser.try_match(hexbyte)?;
parser.try_match(end)?;
Some(Color {
red: u8::from_str_radix(from_utf8(red).unwrap(), 16).unwrap(),
green: u8::from_str_radix(from_utf8(green).unwrap(), 16).unwrap(),
blue: u8::from_str_radix(from_utf8(blue).unwrap(), 16).unwrap()
})
}
Structs§
- See
Pattern::and
- See
range()
- An interval with a lower and (potentially unbounded) upper bound
- See
noneof()
- See
not
- See
oneof()
- See
optional
- See
Pattern::or
- A byte parser that recognizes
Pattern
s - See
Pattern::repeats
Traits§
- Expresses that the implementing type can be used to match a byte slice
Functions§
- A pattern that fails if the byte at the start of the input is not an ascii alphabetic character
- A pattern that fails if the byte at the start of the input is not an ascii digit
- A pattern that fails if the input is not empty
- A pattern that fails if the byte at the start of the input is not a hexadecimal character
- Inverse of
oneof
- Expresses pattern negation
- Returns a pattern that will match any one of the bytes in
alternatives
- Expresses an optional pattern
- Returns a pattern that will match any byte in the closed interval
[lo, hi]