给定一个原始输入流,&[u16]
考虑到 nom 期望&str
作为输入,我如何使用 nom 来解析它?
例如,给定以下数据:
pub const RAW_INPUT: &[u16] = &[102, 111, 111];
我想把它解析成字符串“foo”。
有几种方法可以做到这一点。我对modbus一无所知,所以我假设输入看起来像你RAW_INPUT
上面的。首先,您可以使用as
将 u16 转换为 u8。这将默默地截断大于 255 的值。另一种更安全的方法是使用std::convert::TryFrom:
在某些情况下,可能会以受控方式失败的简单且安全的类型转换。它是 的倒数
TryInto
。当您进行可能很容易成功但也可能需要特殊处理的类型转换时,这很有用。例如,无法使用trait将 an 转换
i64
为 an ,因为 an可能包含 an无法表示的值,因此转换会丢失数据。这可以通过将 截断为 a (基本上给出' 的值取模)或通过简单地返回或通过其他方法来处理。该特征旨在用于完美转换,因此该特征会在类型转换可能出错时通知程序员并让他们决定如何处理它。i32
From
i64
i32
i64
i32
i64
i32::MAX
i32::MAX
From
TryFrom
您可以在Rust Playground上玩一些说明性代码:
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use std::num::TryFromIntError;
use std::str;
pub const RAW_BAD_INPUT: &[u16] = &[102, 111, 111, 300];
pub const RAW_GOOD_INPUT: &[u16] = &[102, 111, 111];
/// Converts using `as`. Demonstrates truncation.
#[test]
fn test_truncating() {
let expected = vec![102, 111, 111, 44]; // Note: 44
let actual = RAW_BAD_INPUT
.iter()
.map(|val| *val as u8)
.collect::<Vec<u8>>();
assert_eq!(expected, actual);
}
/// Demonstrates conversion using `TryFrom` on input with values that
/// would be truncated
#[test]
fn test_try_from_bad() {
let actual: Vec<Result<u8, TryFromIntError>> =
RAW_BAD_INPUT.iter().map(|val| u8::try_from(*val)).collect();
assert_eq!(actual[0].unwrap(), 102u8);
assert_eq!(actual[1].unwrap(), 111u8);
assert_eq!(actual[2].unwrap(), 111u8);
assert!(actual[3].is_err());
}
/// Demonstrates conversion using `TryFrom` on input with values
/// that would not be truncated. Also parses the Vec<u8> as a UTF-8
/// encoded string
#[test]
fn test_try_from_ok() {
let intermediate: Vec<u8> = RAW_GOOD_INPUT
.iter()
.map(|val| u8::try_from(*val).unwrap())
.collect();
let actual = match str::from_utf8(&intermediate) {
Ok(s) => s,
Err(e) => panic!("Invalid UTF-8: {}", e),
};
assert_eq!("foo", actual);
}
}
使用 中的代码test_try_from_ok
,您现在应该有一个String
包含您希望用来解析的数据nom
。
鉴于:
pub const RAW_INPUT: &[u16] = &[102, 111, 111];
我最终将输入转换为u8
第一个:
let xs = RAW_INPUT
.iter()
.flat_map(|x| x.to_be_bytes().to_vec())
.collect::<Vec<u8>>();
然后用 nom 正常解析它。