Utility library for parsing data from an input string, or stdin if built with the std
feature.
Supports no_std contexts when built without the std
feature enabled. Requires the alloc crate.
The std
feature is enabled by default.
Supports parsing one or multiple values from a string. Can parse primitives, Strings, or any
type which derives the TryParse
trait.
Supports parsing primitives from hexadecimal or binary values.
The try_parse
, parse
, try_scan
and scan
macros put high emphasis on deducing types,
meaning you rarely need to specify the type yourself unless you want to enforce a specific
type, or there's missing context.
parse
and try_parse
usage``rust
//
parseand
tryparseparses a single value from the source string,
// and has more cohesive errors than
scanand
tryscan`.
// Attempts to parse a number from source
using try_parse
let source = String::from("number: 30");
let number = tryparse!(source => "number: {}");
asserteq!(number, Ok(30));
// Internally calls try_parse
and unwraps the result.
let source = "hello, world!";
let value: String = parse!(source => "hello, {}!");
asserteq!(value, "world".tostring());
```
scan
and try_scan
usage``rust
//
scanand
tryscanhas less cohesive erros than
parseand
//
tryparse`, but allows parsing multiple values from a single
// source string.
// Example of parsing 4 strings from one source string using try_scan
let source = String::from("this is four words!");
let matched = tryscan!(source => "{} {} {} {}!");
asserteq!(
matched,
Ok((
"this".tostring(),
"is".tostring(),
"four".tostring(),
"words".tostring()
))
);
// Interally calls try_scan
and unwraps the result.
let source = "add 20, 30";
let (left, right): (u32, u32) = scan!(source => "add {}, {}");
assert_eq!(left + right, 50);
```
std
feature.```rust let name: String = parse!("hello! my name is {}."); println!("hello, {name}!");
let tryparse: Result
// You can also use stdin for scan
and try_scan
let (a, b, c): (u32, u32, u32) = scan!("{} + {} = {}");
assert_eq!(a + b, c);
let tryscan: Result<(u32, u32, u32), _> = tryscan!("{} + {} = {}"); match try_scan { Ok((a,b,c)) => println!("{a} + {b} = {c}"), Err(e) => println!("an erro occured: {e:?}"), } ```
```rust let mut number = -1; tryparse!("input number: 20" => "input number: {number}"); asserteq!(number, 20);
let (mut l, mut r) = ("".tostring(), "".tostring()); tryscan!("hello world!" => "{l} {r}").expect("failed to parse"); asserteq!((l, r), ("hello".tostring(), "world!".tostring()));
// If the parsing failed, an error is returned by the macro call. let mut number: i32 = -1; match tryparse!("fail 20" => "success {number}"){ Ok() => println!("parsed value: {number}"), Err(_) => println!("failed to parse input string"), }
// Inlining can also be paired with returning values in scan
and try_scan
.
let (mut left, mut right) = ("".tostring(), "".tostring());
let middle = scan!("left middle right" => "{left} {} {right}");
asserteq!(
(left, middle, right),
("left".tostring(), "middle".tostring(), "right".tostring())
);
// scan
and try_scan
can mix both inlining matching values,
// or alternatively capture them as a return value.
let (mut x, mut y, mut z) = (0, 0, 0);
let v = tryscan!("10, 20, 30, 40" => "{}, {x}, {y}, {z}");
asserteq!((v, x, y, z), (Ok(10), 20, 30, 40));
let (mut x, mut y, mut z) = (0, 0, 0); let v = tryscan!("10, 20, 30, 40" => "{x}, {}, {y}, {z}"); asserteq!((v, x, y, z), (Ok(20), 10, 30, 40));
let (mut x, mut y, mut z) = (0, 0, 0); let v = tryscan!("10, 20, 30, 40" => "{x}, {y}, {}, {z}"); asserteq!((v, x, y, z), (Ok(30), 10, 20, 40));
let (mut x, mut y, mut z) = (0, 0, 0); let v = tryscan!("10, 20, 30, 40" => "{x}, {y}, {z}, {}"); asserteq!((v, x, y, z), (Ok(40), 10, 20, 30));
let (mut x, mut y) = (0, 0); let v = tryscan!("10, 10, 20, 20" => "{x}, {}, {y}, {}"); asserteq!(v, Ok((x,y))); ```
```rust
// Need to specify 'u64' here, since otherwise the value will be too large.
let hex: Result
let bin: Result
let (bin, hex) = scan!("bin: 0b101, hex: 0xFE" => "bin: 0b{:b}, hex: 0x{:x}"); assert_eq!((bin, hex), (0b101u32, 0xFEu32));
// Parsing as hexadecimal or binary also works with inlining. let mut bin = -1; parse!("binary value: 101" => "binary value: {bin:b}"); assert_eq!(bin, 0b101);
let (mut bin, mut hex) = (-1, -1); scan!("bin: 1111, hex: F" => "bin: {bin:b}, hex: {hex:x}"); assert_eq!((bin, hex), (0b1111, 0xF)); ```
License: MIT