给出&[u16]
的原始输入流,考虑到nom期望&str
作为输入,我如何使用nom对其进行解析?
例如,给定以下数据:
pub const RAW_INPUT: &[u16] = &[102, 111, 111];
我想将其解析为字符串“ foo”。
答案 0 :(得分:0)
您可以通过以下两种方法进行此操作。我对modbus一无所知,因此我假设输入看起来像您上面的RAW_INPUT
。首先,您可以使用as
将u16强制转换为u8。这将以静默方式截断大于255的值。另一种更安全的方法是使用std::convert::TryFrom:
简单安全的类型转换,在某些情况下可能会以受控方式失败。它是
TryInto
的倒数。当您执行类型转换但可能成功但又需要特殊处理的类型转换时,这很有用。例如,无法使用
i64
特性将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
解析的数据。
答案 1 :(得分:0)
给出:
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正常解析。