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 crate’s entry point is the Matches struct. It contains an array of input segments that
have been matched. The array is populated by repeatedly calling .add() with a
pattern argument.
Patterns can be combined using combinatorial logic to express more complex rules about what a byte (or sequence of bytes should look like)
Examples
HTTP request line
Say you wanted 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, Matches};
// This input would probably come from a TcpStream
let input = b"GET /hello?value=world HTTP/1.1\r\n";
let matches = Matches::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 result = matches
.pattern(method_pattern)?
.ignore(" ")?
.pattern(request_target_pattern)?
.ignore(" ")?
.pattern(version_pattern)?
.ignore("\r\n".and(bparse::end))?;
// Et voila
let [method, request_target, version] = result.0;
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, Matches};
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 = bparse::range(b'0', b'9')
.or(bparse::range(b'A', b'F'))
.or(bparse::range(b'a', b'f'))
.repeats(2);
let [red, green, blue] = Matches::new(input.as_bytes())
.ignore("#")?
.pattern(hexbyte)?
.pattern(hexbyte)?
.pattern(hexbyte)?
.ignore(bparse::end)?
.0;
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
- A container of matched slices. Also stores the remaining input
- See
noneof() - See
Pattern::not - See
oneof() - See
Pattern::or - 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 - Returns a pattern that will match any one of the bytes in
alternatives - Returns a pattern that will match any byte in the closed interval
[lo, hi]