Как преобразовать целое число u128 в Uuid с помощью nom - PullRequest
3 голосов
/ 13 марта 2020

У меня есть пакет двоичных данных с 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"

Ответы [ 2 ]

3 голосов
/ 13 марта 2020

В номе 5 вы можете просто использовать classi c rust way, пример самоописывает:

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);
}
1 голос
/ 13 марта 2020

Я только что исправил вашу попытку. Вы можете реализовать, или использовать более полезную ошибку.

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