A simple string parsing utility library for Rust, supporting no_std contexts.

Related tags

Utilities strp
Overview

strp

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.

Basic parse and try_parse usage

"number: {}"); assert_eq!(number, Ok(30)); // Internally calls `try_parse` and unwraps the result. let source = "hello, world!"; let value: String = parse!(source => "hello, {}!"); assert_eq!(value, "world".to_string());">
// `parse` and `try_parse` parses a single value from the source string,
// and has more cohesive errors than `scan` and `try_scan`.

// Attempts to parse  a number from `source` using `try_parse`
let source = String::from("number: 30");
let number = try_parse!(source => "number: {}");
assert_eq!(number, Ok(30));

// Internally calls `try_parse` and unwraps the result.
let source = "hello, world!";
let value: String = parse!(source => "hello, {}!");
assert_eq!(value, "world".to_string());

Basic scan and try_scan usage

"{} {} {} {}!"); assert_eq!( matched, Ok(( "this".to_string(), "is".to_string(), "four".to_string(), "words".to_string() )) ); // 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);">
// `scan` and `try_scan` has less cohesive erros than `parse` and
// `try_parse`, 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 = try_scan!(source => "{} {} {} {}!");
assert_eq!(
    matched,
    Ok((
        "this".to_string(),
         "is".to_string(),
         "four".to_string(),
         "words".to_string()
    ))
);

// 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);

Using stdin with the std feature.

= try_parse!("Please, enter your name: {}."); match try_parse { Ok(name) => println!("Thank you for inputing your name, {name}!"), Err(_) => println!("No name was given."), } // You can also use stdin for `scan` and `try_scan` let (a, b, c): (u32, u32, u32) = scan!("{} + {} = {}"); assert_eq!(a + b, c); let try_scan: Result<(u32, u32, u32), _> = try_scan!("{} + {} = {}"); match try_scan { Ok((a,b,c)) => println!("{a} + {b} = {c}"), Err(e) => println!("an erro occured: {e:?}"), }">
let name: String = parse!("hello! my name is {}.");
println!("hello, {name}!");

let try_parse: Result<String, _> = try_parse!("Please, enter your name: {}.");
match try_parse {
    Ok(name) => println!("Thank you for inputing your name, {name}!"),
    Err(_) => println!("No name was given."),
}

// You can also use stdin for `scan` and `try_scan`
let (a, b, c): (u32, u32, u32) = scan!("{} + {} = {}");
assert_eq!(a + b, c);

let try_scan: Result<(u32, u32, u32), _> = try_scan!("{} + {} = {}");
match try_scan {
    Ok((a,b,c)) => println!("{a} + {b} = {c}"),
    Err(e) => println!("an erro occured: {e:?}"),
}

Inlining matched values.

"input number: {number}"); assert_eq!(number, 20); let (mut l, mut r) = ("".to_string(), "".to_string()); try_scan!("hello world!" => "{l} {r}").expect("failed to parse"); assert_eq!((l, r), ("hello".to_string(), "world!".to_string())); // If the parsing failed, an error is returned by the macro call. let mut number: i32 = -1; match try_parse!("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) = ("".to_string(), "".to_string()); let middle = scan!("left middle right" => "{left} {} {right}"); assert_eq!( (left, middle, right), ("left".to_string(), "middle".to_string(), "right".to_string()) ); // `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 = try_scan!("10, 20, 30, 40" => "{}, {x}, {y}, {z}"); assert_eq!((v, x, y, z), (Ok(10), 20, 30, 40)); let (mut x, mut y, mut z) = (0, 0, 0); let v = try_scan!("10, 20, 30, 40" => "{x}, {}, {y}, {z}"); assert_eq!((v, x, y, z), (Ok(20), 10, 30, 40)); let (mut x, mut y, mut z) = (0, 0, 0); let v = try_scan!("10, 20, 30, 40" => "{x}, {y}, {}, {z}"); assert_eq!((v, x, y, z), (Ok(30), 10, 20, 40)); let (mut x, mut y, mut z) = (0, 0, 0); let v = try_scan!("10, 20, 30, 40" => "{x}, {y}, {z}, {}"); assert_eq!((v, x, y, z), (Ok(40), 10, 20, 30)); let (mut x, mut y) = (0, 0); let v = try_scan!("10, 10, 20, 20" => "{x}, {}, {y}, {}"); assert_eq!(v, Ok((x,y)));">
let mut number = -1;
try_parse!("input number: 20" => "input number: {number}");
assert_eq!(number, 20);

let (mut l, mut r) = ("".to_string(), "".to_string());
try_scan!("hello world!" => "{l} {r}").expect("failed to parse");
assert_eq!((l, r), ("hello".to_string(), "world!".to_string()));

// If the parsing failed, an error is returned by the macro call.
let mut number: i32 = -1;
match try_parse!("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) = ("".to_string(), "".to_string());
let middle = scan!("left middle right" => "{left} {} {right}");
assert_eq!(
    (left, middle, right),
    ("left".to_string(), "middle".to_string(), "right".to_string())
);

// `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 = try_scan!("10, 20, 30, 40" => "{}, {x}, {y}, {z}");
assert_eq!((v, x, y, z), (Ok(10), 20, 30, 40));

let (mut x, mut y, mut z) = (0, 0, 0);
let v = try_scan!("10, 20, 30, 40" => "{x}, {}, {y}, {z}");
assert_eq!((v, x, y, z), (Ok(20), 10, 30, 40));

let (mut x, mut y, mut z) = (0, 0, 0);
let v = try_scan!("10, 20, 30, 40" => "{x}, {y}, {}, {z}");
assert_eq!((v, x, y, z), (Ok(30), 10, 20, 40));

let (mut x, mut y, mut z) = (0, 0, 0);
let v = try_scan!("10, 20, 30, 40" => "{x}, {y}, {z}, {}");
assert_eq!((v, x, y, z), (Ok(40), 10, 20, 30));

let (mut x, mut y) = (0, 0);
let v = try_scan!("10, 10, 20, 20" => "{x}, {}, {y}, {}");
assert_eq!(v, Ok((x,y)));

Hexadecimal and binary parsing.

"input hex: 0x{:x}"); assert_eq!(hex, Ok(0x0123456789ABCDEF)); let bin: Result = try_parse!("input bin: 0b11110001" => "input bin: 0b{:b}"); assert_eq!(bin, Ok(0b11110001)); 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));">
// Need to specify 'u64' here, since otherwise the value will be too large.
let hex: Result<u64, _> =
    try_parse!("input hex: 0x0123456789ABCDEF" => "input hex: 0x{:x}");
assert_eq!(hex, Ok(0x0123456789ABCDEF));

let bin: Result<u32, _> = try_parse!("input bin: 0b11110001" => "input bin: 0b{:b}");
assert_eq!(bin, Ok(0b11110001));

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

You might also like...
SubStrings, Slices and Random String Access in Rust

SubStrings, Slices and Random String Access in Rust This is a simple way to do it. Description Rust string processing is kind of hard, because text in

A string truncator and scroller written in Rust
A string truncator and scroller written in Rust

scissrs A string truncator and scroller written in Rust. Usage scissrs --help covers the definitions of this program's flags.

microtemplate - A fast, microscopic helper crate for runtime string interpolation.

microtemplate A fast, microscopic helper crate for runtime string interpolation. Design Goals Very lightweight: I want microtemplate to do exactly one

A memory efficient immutable string type that can store up to 24* bytes on the stack

compact_str A memory efficient immutable string type that can store up to 24* bytes on the stack. * 12 bytes for 32-bit architectures About A CompactS

An efficient method of heaplessly converting numbers into their string representations, storing the representation within a reusable byte array.

NumToA #![no_std] Compatible with Zero Heap Allocations The standard library provides a convenient method of converting numbers into strings, but thes

Count and convert between different indexing schemes on utf8 string slices

Str Indices Count and convert between different indexing schemes on utf8 string slices. The following schemes are currently supported: Chars (or "Unic

Verbump - A simple utility written in rust to bump and manage git semantic version tags.

Verbump - A simple utility written in rust to bump and manage git semantic version tags.

mollusc is a collection of pure-Rust libraries for parsing, interpreting, and analyzing LLVM.

mollusc is a collection of pure-Rust libraries for parsing, interpreting, and analyzing LLVM.

A Rust utility library, making easier by taking the hassle out of working. :octocat:
A Rust utility library, making easier by taking the hassle out of working. :octocat:

reddish A Rust utility library, making easier by taking the hassle out of working. Usage Add this to your Cargo.toml: [dependencies] reddish = "0.2.0"

Owner
iqon
A hobbyist programmer.
iqon
An annotated string type in Rust, made up of string slices

A string type made up of multiple annotated string slices.

Togglebit 3 Dec 29, 2022
An unofficial and incomplete no_std Rust library for implementing the ElectricUI Binary Protocol

An unofficial and incomplete no_std Rust library for implementing the ElectricUI Binary Protocol

Jon 2 Mar 29, 2022
Garden monitoring system using m328p Arduino Uno boards. 100% Rust [no_std] using the avr hardware abstraction layer (avr-hal)

uno-revive-rs References Arduino Garden Controller Roadmap uno-revive-rs: roadmap Components & Controllers 1-2 Uno R3 m328p Soil moisture sensor: m328

Ethan Gallucci 1 May 4, 2022
Rust no_std, embedded_hal board support package for the Electro-Smith Daisy platform.

Daisy Rust no_std, embedded_hal board support package for the Electro-Smith Daisy platform. This project was forked from antoinevg/daisy_bsp. Supporte

zlosynth 5 Dec 4, 2022
Dyadic rationals for `no_std` targets

dyadic ?? Dyadic rationals for no_std targets.

Vitaly Domnikov 2 Dec 16, 2021
How to bootstrap support for a no_std target

The Embedonomicon How to bootstrap support for a no_std target This book is hosted at https://docs.rust-embedded.org/embedonomicon/ This project is de

Rust Embedded 191 Dec 20, 2022
A simple string interner / symbol table for Rust projects.

Symbol Interner A small Rust crate that provides a naïve string interner. Consult the documentation to learn about the types that are exposed. Install

Ryan Chandler 1 Nov 18, 2021
A flexible, simple to use, immutable, clone-efficient String replacement for Rust

A flexible, simple to use, immutable, clone-efficient String replacement for Rust. It unifies literals, inlined, and heap allocated strings into a single type.

Scott Meeuwsen 119 Dec 12, 2022
Rust library to detect bots using a user-agent string

Rust library to detect bots using a user-agent string

Bryan Morgan 8 Dec 21, 2022
sgmlish is a library for parsing, manipulating and deserializing SGML.

sgmlish is a library for parsing, manipulating and deserializing SGML. It's not intended to be a full-featured implementation of the SGML spec

Daniel Luz 6 Dec 14, 2022