serde:顶层状态反序列化

3

我试图反序列化一个二进制格式 (OpenType),其中包含多个表格(二进制结构)的数据。我想能够独立地对这些表进行反序列化(因为它们在顶层文件结构中的存储方式;可以将它们视为单独的文件,所以必须单独进行反序列化),但有时它们之间存在依赖关系。

一个简单的例子是loca表,它包含一个数组,该数组可能是16位或32位的偏移量,具体取决于head表中的indexToLocFormat字段的值。作为一个更复杂的例子,这些loca表中的偏移量又被用作glyf表中二进制数据的偏移量,以定位元素。因此,我需要以某种方式将indexToLocFormatloca: 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解析器,那是因为我想要同时读取和写入字体文件。)

1个回答

0
其实,我觉得我想通了。诀窍在于分阶段进行反序列化。不要调用反序列化模块的from_bytes函数(它包装了结构创建和T::deserialize调用),而是这样做:
use serde::de::DeserializeSeed; // Having this trait in scope is also key
let mut de = Deserializer::from_bytes(&binary_loca_table);
let ssd: SomeSpecialistDeserializer { ... configuration goes here .. };
let loca_table: Vec<u32> = ssd.deserialize(&mut de).unwrap();

在这种情况下,我使用一个像这样定义的LocaDeserializer
pub struct LocaDeserializer { locaIs32Bit: bool }

impl<'de> DeserializeSeed<'de> for LocaDeserializer {
    type Value = Vec<u32>;

    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        struct LocaDeserializerVisitor {
            locaIs32Bit: bool,
        }

        impl<'de> Visitor<'de> for LocaDeserializerVisitor {
            type Value = Vec<u32>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "a loca table")
            }

            fn visit_seq<A>(self, mut seq: A) -> std::result::Result<Vec<u32>, A::Error>
            where
                A: SeqAccess<'de>,
            {
                if self.locaIs32Bit {
                    Ok(seq.next_element::<u32>()?.ok_or_else(|| serde::de::Error::custom(format!("Expecting a 32 bit glyph offset")))?)
                } else {
                    Ok(seq.next_element::<u16>()?.ok_or_else(|| serde::de::Error::custom(format!("Expecting a 16 bit glyph offset")))?
                        .iter()
                        .map(|x| (*x as u32) * 2)
                        .collect())
                }
            }
        }

        deserializer.deserialize_seq(LocaDeserializerVisitor {
            locaIs32Bit: self.locaIs32Bit,
        })
    }
}

现在:

    fn loca_de() {
        let binary_loca = vec![
            0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a,
        ];
        let mut de = Deserializer::from_bytes(&binary_loca);
        let cs: loca::LocaDeserializer = loca::LocaDeserializer { locaIs32Bit: false };
        let floca: Vec<u32> = cs.deserialize(&mut de).unwrap();
        println!("{:?}", floca);
        // [2, 0, 2, 0, 0, 52]

        let mut de = Deserializer::from_bytes(&binary_loca);
        let cs: loca::LocaDeserializer = loca::LocaDeserializer { locaIs32Bit: true };
        let floca: Vec<u32> = cs.deserialize(&mut de).unwrap();
        println!("{:?}", floca);
        // [65536, 65536, 26]
}

Serde非常好用 - 一旦你理解了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接