我的Rust二进制代码库有问题。序列化向量时,始终假设前缀长度为8个字节。当您始终使用Bincode编码数据时,这是一个很好的假设,因为Bincode可以读取它自己的序列化数据。
我处于无法影响串行器的情况,因为我没有编写串行器,并且由于遗留原因,它必须保持不变。它将其矢量编码为一个长度为前缀的数组,其中的前缀始终为2个字节(或者在某些情况下为4个字节,但是我知道这些情况。一旦我知道如何使用2个字节来做,则4个字节不应为问题)。
如何使用Bincode(和Serde)对这些字段进行反序列化?我可以解决以二进制编码硬编码的默认8个字节的长度吗?
答案 0 :(得分:4)
Bincode不应该与任何现有的序列化程序或标准兼容。根据评论,您尝试读取的格式也不是。
我建议您获得bincode来源(它们是MIT许可的,因此您基本上可以随心所欲地对它们进行任何操作),并对其进行修改以适合您的格式(并为其命名并包含它在您的项目中。)
serde::Deserializer
和基础的data model都有很好的文档说明,在bincode中的实现很难找到(在de/mod.rs
中),因此以它为起点并进行调整根据需要。
答案 1 :(得分:0)
我已经找到了一种(可能非常丑陋的)方式来实现它,而无需实现自己的反序列化器— Bincode毕竟可以做到。看起来像这样:
impl<'de> Deserialize<'de> for VarLen16 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VarLen16Visitor;
impl<'de> Visitor<'de> for VarLen16Visitor {
type Value = VarLen16;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("VarLen16")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut res: Vec<u8> = vec![];
let length: u16 = seq
.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
for i in 0..length {
res.push(
seq.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(1, &self))?,
);
}
return Ok(VarLen16(res));
}
}
return Ok(deserializer.deserialize_tuple(1 << 16, VarLen16Visitor)?);
}
}
简而言之,我使系统认为我反序列化了一个元组,在该元组中,我将长度设置为所需的最大长度。我已经测试过了,它实际上并没有分配那么多的内存。然后,我将长度表示为该元组的一部分,先阅读该长度,然后继续阅读直到该长度指示我为止。它虽然不漂亮,但肯定可以。