我试图反序列化一个二进制格式 (OpenType),其中包含多个表格(二进制结构)的数据。我想能够独立地对这些表进行反序列化(因为它们在顶层文件结构中的存储方式;可以将它们视为单独的文件,所以必须单独进行反序列化),但有时它们之间存在依赖关系。
一个简单的例子是loca
表,它包含一个数组,该数组可能是16位或32位的偏移量,具体取决于head
表中的indexToLocFormat
字段的值。作为一个更复杂的例子,这些loca
表中的偏移量又被用作glyf
表中二进制数据的偏移量,以定位元素。因此,我需要以某种方式将indexToLocFormat
和loca: Vec<32>
传递给反序列化器。
显然,我需要自己实现Deserialize
并编写访问程序,并且我已经掌握了如何做到这一点。当存在从一个表到子表的依赖关系时,我还能够使用表的访问程序中的deserialize_seed
来处理这个问题。但是,我不知道如何将这些信息应用于在表之间传递信息。
我认为需要在构建序列化对象时存储基本配置信息(例如indexToLocFormat
的值和偏移量数组):
pub struct Deserializer<'de> {
input: &'de [u8],
ptr: usize,
locaShortVersion: Option<bool>,
glyfOffsets: Option<Vec<u32>>,
...
}
问题在于当我在结构体的 Visitor 实现内部时,不知道如何检索那些信息;我不知道如何访问反序列化器对象,更不用说如何编写代码以获取 我的 反序列化器对象及其配置字段,而不仅仅是一个通用的
serde::de::Deserializer
对象:impl<'de> Visitor<'de> for LocaVisitor {
type Value = Vec<u32>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "A loca table")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let locaShortVersion = /* what goes here? */;
if locaShortVersion {
Ok(seq.next_element::Vec<u16>()?
.ok_or_else(|| serde::de::Error::custom("Oops"))?
.map { |x| x as u32 }
} else {
Ok(seq.next_element::Vec<u32>()?
.ok_or_else(|| serde::de::Error::custom("Oops"))?
}
}
}
(这里有一些糟糕的代码;如果你想知道我为什么要编写另一个OpenType解析器,那是因为我想要同时读取和写入字体文件。)