这段代码完全按照我的要求序列化一个32字节的数组:
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
struct Hash([u8; 32]);
let hash = Hash([1u8; 32]);
let hash_bin = bincode::serialize(&hash).unwrap();
assert_eq!(hash_bin, [1u8; 32]);
它是如何工作的?
根据https://serde.rs/impl-serializer.html,有一个serialize_bytes()
函数,但是在bincode版本中,它会在数据前面添加一个长度。
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
O::IntEncoding::serialize_len(self, v.len())?;
self.writer.write_all(v).map_err(Into::into)
}
代码(上面)调用Serialize中的哪个函数来将32个字节序列化为不带长度前缀的自身?
上下文:我正在为一个类型实现一个客户序列化,我希望它(在某些情况下)序列化字节数组,以便bincode将它们编码为没有长度前缀的字节。这是一个问题,因为调用serialize_bytes()
会添加一个长度前缀。
我想了解默认情况下字节数组是如何序列化的,因为我不知道调用哪个方法来代替serialize_bytes()
来获取没有长度前缀的字节。
1条答案
按热度按时间h79rfbju1#
如何序列化
[u8; N]
和[u8]
?直截了当地说,这里是
serde
1.0.151如何实现每个方法的。serialize_bytes
实际上不是serde
的一部分,因此它被视为一个序列。方法
serialize_tuple
和collect_seq
由您正在使用的特定序列化器实现。简单的方法
一个常见的问题是
serde
只为长度不超过32的数组实现Serialize
/Deserialize
。最简单的方法是使用像serde_with
这样的crate,它添加了额外的序列化/反序列化实现,您可以将其附加到您的结构体中。下面是一个取自其文档的示例:我们如何自己实现它?Rust Playground
一米十一分
执行序列化实际上非常简单。Serde没有数组的概念,所以我们需要在
serialize_tuple
或serialize_seq
之间进行选择。在幕后,唯一的区别是serialize_seq
可能没有已知的长度,所以我们可以选择serialize_tuple
。一米十六分一秒
另一方面,反序列化变得有点复杂。我们需要定义一个访问者,然后指定应该如何访问每个元素。我写出了一个简单的例子,说明在数组的一般情况下如何完成它,但这不是最佳的解决方案,因为它首先被解串到堆栈上。我还必须使用
unsafe
代码一次只初始化数组的一个元素,但是如果使用T: Default
或者如果替代地使用如Vec<T>
的扩展数据结构,则可以容易地去除unsafe
代码。通常,这更倾向于作为在序列上实现反串行化的指南。如果有人好奇
derive(Deserialize)
是如何处理结构体的,我推荐大家看一下Rust Playground,我在其中扩展了宏,然后清理了输出,使其更易于阅读,了解serialize/deserialize是如何工作的,可以真正帮助揭开这个过程的神秘面纱。