代码之家  ›  专栏  ›  技术社区  ›  Tobias Hermann

如何使用Serde(反)序列化大于32个元素的数组,例如[u8;128]?

  •  20
  • Tobias Hermann  · 技术社区  · 7 年前

    我有一个包含字节数组的结构,我想将其序列化并反序列化为二进制,但它只适用于数组 up to 32 elements .

    下面是我的最小示例代码

    主要的卢比 :

    #[macro_use]
    extern crate serde_derive;
    extern crate serde;
    extern crate bincode;
    
    use bincode::{serialize, deserialize, Infinite};
    
    const BYTECOUNT: usize = 32; // 33 and more does not work, I need 128
    type DataArr = [u8; BYTECOUNT];
    
    #[derive(Serialize, Deserialize, Debug)]
    struct Entry {
        number: i64,
        data: DataArr
    }
    
    fn main() {
        let mut my_entry = Entry { number: 12345, data: [0; BYTECOUNT] };
        my_entry.data[4] = 42;
    
        // Convert the Entry to binary.
        let serialized: Vec<u8> = serialize(&my_entry, Infinite).unwrap();
        println!("serialized = {:?}", serialized);
    
        // Convert the binary representation back to an Entry.
        let deserialized: Entry = deserialize(&serialized).unwrap();
        println!("deserialized = {:?}", deserialized);
    }
    

    Cargo.toml :

    [package]
    name = "array_serialization_test"
    version = "0.1.0"
    
    [dependencies]
    serde = "*"
    serde_derive = "*"
    bincode = "*"
    

    输出:

    serialized = [57, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    deserialized = Entry { number: 12345, data: [0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
    

    如何使其适用于阵列中的128个元素?我可以手动扩展吗 array_impls! 在我的用户代码中?是否有其他方法?

    我认为这个问题不同于 How do I map a C struct with padding over 32 bytes using serde and bincode? 因为我实际上需要数组的内容,因为它不仅仅用于填充。我还想知道我是否可以延长 array\u impls! 在我的代码上。

    2 回复  |  直到 4 年前
        1
  •  14
  •   dtolnay    7 年前

    目前Serde无法提供 Serialize Deserialize 为其工作的impls 每一个 数组大小。此已被阻止 const generics 该项目正在进行中,有望在2018年晚些时候每晚落地。

    现在,您可以定义自己的“大数组”助手,它可以序列化和反序列化板条箱中使用的任何特定大小的数组。要使用大数组辅助对象的字段需要标记为 #[serde(with = "BigArray")] 否则Serde会寻找不存在的 序列化 反序列化 impls公司。

    #[macro_use]
    extern crate serde_derive;
    
    extern crate serde;
    extern crate bincode;
    
    mod big_array;
    use big_array::BigArray;
    
    const BYTECOUNT: usize = 128;
    type DataArr = [u8; BYTECOUNT];
    
    #[derive(Serialize, Deserialize)]
    struct Entry {
        number: i64,
        #[serde(with = "BigArray")]
        data: DataArr
    }
    
    fn main() {
        let mut my_entry = Entry { number: 12345, data: [0; BYTECOUNT] };
        my_entry.data[4] = 42;
    
        // Convert the Entry to binary.
        let serialized: Vec<u8> = bincode::serialize(&my_entry).unwrap();
        println!("serialized = {:?}", serialized);
    
        // Convert the binary representation back to an Entry.
        let deserialized: Entry = bincode::deserialize(&serialized).unwrap();
        println!("deserialized = {} {:?}", deserialized.number, &deserialized.data[..]);
    }
    

    可以在中定义大数组辅助对象 src/big_array.rs 如下所示。如果你想拥有它,也许这会是一个很好的板条箱!

    use std::fmt;
    use std::marker::PhantomData;
    use serde::ser::{Serialize, Serializer, SerializeTuple};
    use serde::de::{Deserialize, Deserializer, Visitor, SeqAccess, Error};
    
    pub trait BigArray<'de>: Sized {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where S: Serializer;
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where D: Deserializer<'de>;
    }
    
    macro_rules! big_array {
        ($($len:expr,)+) => {
            $(
                impl<'de, T> BigArray<'de> for [T; $len]
                    where T: Default + Copy + Serialize + Deserialize<'de>
                {
                    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                        where S: Serializer
                    {
                        let mut seq = serializer.serialize_tuple(self.len())?;
                        for elem in &self[..] {
                            seq.serialize_element(elem)?;
                        }
                        seq.end()
                    }
    
                    fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error>
                        where D: Deserializer<'de>
                    {
                        struct ArrayVisitor<T> {
                            element: PhantomData<T>,
                        }
    
                        impl<'de, T> Visitor<'de> for ArrayVisitor<T>
                            where T: Default + Copy + Deserialize<'de>
                        {
                            type Value = [T; $len];
    
                            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                                formatter.write_str(concat!("an array of length ", $len))
                            }
    
                            fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error>
                                where A: SeqAccess<'de>
                            {
                                let mut arr = [T::default(); $len];
                                for i in 0..$len {
                                    arr[i] = seq.next_element()?
                                        .ok_or_else(|| Error::invalid_length(i, &self))?;
                                }
                                Ok(arr)
                            }
                        }
    
                        let visitor = ArrayVisitor { element: PhantomData };
                        deserializer.deserialize_tuple($len, visitor)
                    }
                }
            )+
        }
    }
    
    big_array! {
        40, 48, 50, 56, 64, 72, 96, 100, 128, 160, 192, 200, 224, 256, 384, 512,
        768, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
    }
    
        2
  •  1
  •   fadedbee    4 年前

    我想这只是等待 const generics support 在塞尔德。