如何使用Serde和Bincode映射具有32字节填充的C结构? [英] How do I map a C struct with padding over 32 bytes using serde and bincode?

查看:146
本文介绍了如何使用Serde和Bincode映射具有32字节填充的C结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Serde和Bincode映射二进制结构.

I'm mapping a binary structure using serde and bincode.

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate bincode;

#[derive(Serialize, Deserialize)]
struct Superblock {
    magic: [u8; 16],
    //reserved: [u8; 492],
    crc: u32,
}

一切正常,但我无法映射保留字段.显然,固定大小的数组仅定义为最大32个字节的大小.

Things work as expected, but I can't map the reserved field. Apparently fixed size arrays are only defined for sizes up to 32 bytes.

如何注册自定义大小的数组,以使填充反序列化?

How do I register my custom-sized array so that the padding gets deserialised?

serde + bincode是正确的方法吗? 我需要控制字节序提供的字节序,并且我喜欢声明式.

Is serde+bincode the right approach? I need control over endianness (which bincode provides) and I like the declarative style.

推荐答案

我建议实现 为自定义类型实现Deserialize .

I'd recommend implementing Serialize and implementing Deserialize for a custom type.

要注意的一件大事是,您根本不关心数据.这意味着没有理由占用内存!我们可以定义类型Reserved,该类型将序列化为一堆字节并从字节反序列化,但实际上在我们的内存结构中不需要任何空间.

The big thing to note is that you don't care about the data at all. This means there's no reason to take up memory! We can define a type Reserved that will serialize to a bunch of bytes and will deserialize from bytes, but doesn't actually require any space in our in-memory struct.

然后,这只是填充trait实现的问题:

Then, it's just a matter of filling in the trait implementation:

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate bincode;

use std::fmt;
use serde::ser::SerializeTuple;

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Superblock {
    magic: [u8; 16],
    reserved: Reserved,
    crc: u32,
}

#[derive(Debug, PartialEq)]
struct Reserved;
const RESERVED_LENGTH: usize = 492;

impl serde::Serialize for Reserved {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: serde::Serializer
    {
        let mut tuple = serializer.serialize_tuple(RESERVED_LENGTH)?;
        for _ in 0..RESERVED_LENGTH {
            tuple.serialize_element(&0xA0_u8)?; // Just to see it easily in the output
        }
        tuple.end()
    }
}

impl<'de> serde::Deserialize<'de> for Reserved {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: serde::Deserializer<'de>
    {
        struct Visitor;
        impl<'de> serde::de::Visitor<'de> for Visitor {
            type Value = Reserved;

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{} bytes", RESERVED_LENGTH)
            }

            fn visit_seq<A>(self, mut tuple: A) -> Result<Self::Value, A::Error>
                where A: serde::de::SeqAccess<'de>,
            {
                for _ in 0..RESERVED_LENGTH {
                    tuple.next_element::<u8>()?;
                }
                Ok(Reserved)
            }
        }

        deserializer.deserialize_tuple(RESERVED_LENGTH, Visitor)
    }
}

fn main() {
    let block = Superblock {
        magic: [
            0x00, 0x01, 0x02, 0x03,
            0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b,
            0x0c, 0x0d, 0x0e, 0x0f,
        ],
        reserved: Reserved,
        crc: 0xffffffff,
    };

    let ser = bincode::serialize(&block, bincode::Infinite).expect("Couldn't serialize");
    println!("length: {}", ser.len());
    println!("{:?}", ser);

    let block2: Superblock = bincode::deserialize(&ser).expect("Couldn't deserialize");
    assert_eq!(block, block2);
    println!("{:?}", block2);

    println!("Takes: {} bytes", std::mem::size_of::<Superblock>());
    // prints "Takes: 20 bytes"
}

这篇关于如何使用Serde和Bincode映射具有32字节填充的C结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆