Есть несколько способов сделать это. Я ничего не знаю о 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
.