#string #parser #binary-parser #primitive #multiple-values #context #hex

无需 std strp

一个简单的字符串解析实用程序包,支持无_std 环境

17 个版本 (5 个稳定版)

1.1.2 2022 年 12 月 16 日
1.1.1 2022 年 11 月 5 日
0.3.6 2022 年 11 月 3 日
0.2.2 2022 年 11 月 2 日
0.1.1 2022 年 11 月 2 日

解析工具 中排名 #81

每月下载量 49

MIT 许可证 MIT

39KB
519

strp

一个用于从输入字符串或(如果构建时启用了 std 功能)stdin 解析数据的实用库。在未启用 std 功能时支持无_std 环境。需要 alloc crate。默认启用 std 功能。

支持从字符串解析一个或多个值。可以解析基本数据类型、字符串或任何实现了 TryParse 特性的类型。

支持从十六进制或二进制值解析基本数据类型。

try_parseparsetry_scanscan 宏非常注重类型推断,这意味着除非你想强制使用特定类型或存在上下文缺失的情况,否则很少需要自己指定类型。

基本 parsetry_parse 使用方法

parsetry_parse 从源字符串解析单个值,并且比 scantry_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());

parse 也不接受一次解析多个值。以下代码无法编译。

let source = "some source"
let ok = parse!(source => "{}"); // Ok!

let err = parse!(source => "{} {}"); // Error! Attempting to parse multiple values with `parse`.

let err = parse!(source => "some source"); // Error! Attempting to parse no values using `parse`.

基本 scantry_scan 使用方法

scantry_scan 的错误不如 parsetry_parse 一致,但允许从单个源字符串解析多个值。

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

scantry_scan 需要同时解析两个或多个值。以下代码无法编译。

let source = "some source";
let ok = scan!(source => "{} {}"); // Ok!

let err = scan!(source => "{}"); // Error! Attempting to parse a single value with `scan`.

let err = scan!(source => "some source"); // Error! Attempting to parse no values using `scan`.

使用 std 功能与 stdin 一起使用。

// Uses stdin as a source string.
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:?}"),
}

内联匹配的值。

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

十六进制和二进制解析。

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

许可证:MIT

依赖项

~1.5MB
~35K SLoC