如何使用 nom 将 u128 整数转换为 Uuid

How to transform a u128 integer to an Uuid with nom

我有一个二进制数据包,其中包含一个 UUID(16 字节)、一个 1 字节类型字段和 4 个包含浮点值的字节。

如何用nom解析并得到一个元组(Uuid, u8, f32)?

use nom::{
    combinator::map_res, number::complete::le_f32, number::complete::le_u128,
    number::complete::le_u8, sequence::tuple, IResult,
};
use uuid;

fn detect(data: &[u8]) -> IResult<&[u8], (uuid::Uuid, u8, f32)> {
    ???

    /* my attempt so far: 
    map_res(tuple((le_u128, le_u8, le_f32)), |tup| {
        Ok((uuid::Uuid::from_u128(tup.0), tup.1, tup.2))
    })(data)
    */
}

fn main() {
    let pdu = [
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 200, 65,
    ];

    let result = detect(&pdu);
    println!("{:?}", result);
}
[dependencies]
nom = "5"
uuid = "0.8"

在 nom 5 中,您可以使用经典的 Rust 方式,示例是自我描述的:

use nom::combinator;
use nom::number::complete as number;

fn detect(data: &[u8]) -> nom::IResult<&[u8], (uuid::Uuid, u8, f32)> {
    let (data, uuid) = combinator::map(number::le_u128, uuid::Uuid::from_u128)(data)?;
    let (data, type_field) = number::le_u8(data)?;
    let (data, value) = number::le_f32(data)?;

    Ok((data, (uuid, type_field, value)))
}

fn main() {
    let pdu = [
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 200, 65,
    ];

    let result = detect(&pdu);
    println!("{:?}", result);
}

我刚刚修正了你的尝试。您可以实施或使用更有用的错误。

use nom::{
    combinator::map_res, number::complete::le_f32, number::complete::le_u128,
    number::complete::le_u8, sequence::tuple, IResult,
};
use std::fmt::{Display, Formatter};
use uuid;

#[derive(Debug)]
struct Error;

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error")
    }
}

impl std::error::Error for Error {}

fn detect(data: &[u8]) -> IResult<&[u8], (uuid::Uuid, u8, f32)> {
    map_res(
        tuple((le_u128, le_u8, le_f32)),
        |tup: (u128, u8, f32)| -> Result<(uuid::Uuid, u8, f32), Error> {
            Ok((uuid::Uuid::from_u128(tup.0), tup.1, tup.2))
        },
    )(data)
}

fn main() {
    let pdu = [
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 200, 65,
    ];

    let result = detect(&pdu);
    println!("{:?}", result);
}