rust 序列化/反序列化可表示为字节数组的结构

js5cn81o  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(173)

我正在使用一个struct,它大致如下所示:

struct MyStruct {
   // Various fields, most of which do not implement `Serialize` / `Deserialize`
}

struct MyError; // Yes, this implements `std::error::Error`

impl MyStruct {
   fn from_bytes(bytes: [u8; 96]) -> Result<MyStruct, MyError> {
      // Creates a `MyStruct` from an array of exactly 96 bytes.
      // It returns a `MyError` upon failure.
   }

   fn to_bytes(&self) -> [u8; 96] {
      // Serializes `MyStruct` into an array of exactly 96 bytes.
   }
}

现在,我想让MyStruct实现serdeSerializeDeserialize,直觉告诉我它应该很简单(我确实有一些函数已经序列化和反序列化了MyStruct),但是经过几个小时混乱的试验和错误,我卡住了。
我想要的是MyStruct实现SerializeDeserialize,如果我调用bincode::serialize(my_struct),我希望它精确地表示为96字节(即,我希望避免支付无意义的8字节头的成本,该头总是说“下面是96字节的序列”:我已经知道我需要96个字节来表示MyStruct!)。

hgb9j2n6

hgb9j2n61#

你的问题的第一部分可以完成如下:

use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use serde_big_array::BigArray;

#[derive(Serialize, Deserialize)]
struct Wrap {
    #[serde(with = "BigArray")]
    arr: [u8; 96],
}

struct MyStruct {}

struct MyError;

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

impl MyStruct {
    fn from_bytes(bytes: [u8; 96]) -> Result<MyStruct, MyError> {
        todo!()
    }

    fn to_bytes(&self) -> [u8; 96] {
        todo!()
    }
}

impl serde::Serialize for MyStruct {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        Wrap {
            arr: self.to_bytes(),
        }
        .serialize(serializer)
    }
}

impl<'de> serde::Deserialize<'de> for MyStruct {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let bytes = <Wrap>::deserialize(deserializer)?;
        Self::from_bytes(bytes.arr).map_err(D::Error::custom)
    }
}

第二部分比较坚韧,取决于您使用serde的格式。

相关问题