Могу ли я десериализовать векторы с префиксом переменной длины с помощью Bincode? - PullRequest
1 голос
/ 20 мая 2019

У меня проблема с библиотекой бинкодов Rust.Когда он сериализует вектор, он всегда предполагает, что длина префикса составляет 8 байтов.Это хорошее предположение, когда вы всегда кодируете данные с использованием bincode, потому что bincode может читать свои собственные сериализованные данные.

Я нахожусь в ситуации, когда я не могу повлиять на сериализатор, так как я не записывал его, и он должен остатьсято же самое по наследству.Он кодирует свои векторы как массив с префиксом длины, где префикс всегда равен 2 байта (или в некоторых случаях это 4 байта, но я хорошо знаю эти случаи. Как только я знаю, как это сделать с 2 байтами, 4 байта не должны бытьпроблема).

Как я могу использовать bincode (и serde в этом отношении) для десериализации этих полей?Могу ли я работать с 8 байтами по умолчанию, жестко закодированными в bincode?

Ответы [ 2 ]

4 голосов
/ 20 мая 2019

Bincode не должен быть совместимым с любым существующим сериализатором или стандартом.Также, согласно комментарию, формат, который вы пытаетесь прочитать.

Я предлагаю вам получить bincode источники - они имеют лицензию MIT, так что вы можете делать практически все, что угоднопожалуйста, с ними - и измените их в соответствии с вашим форматом (и дайте ему свое имя и включите его в свой проект).

serde::Deserializer довольно хорошо задокументировано, как и лежащая в основе модель данных , и реализация в bincode тривиально найти (в de/mod.rs), поэтому возьмите ее в качестве отправной точки и при необходимости отрегулируйте.

0 голосов
/ 21 мая 2019

Я нашел (возможно, очень уродливый) способ сделать это, не внедрив свой собственный десериализатор - 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)?);
    }
}

Короче говоря, я заставляю систему думать, что я десериализирую кортеж, где я устанавливаю длину на максимум, который мне нужен.Я проверил это, на самом деле он не выделяет столько памяти.Затем я веду себя так, как будто длина является частью этого кортежа, сначала читаю его, а затем продолжаю читать, насколько мне подсказывает эта длина.Это не красиво, но, безусловно, работает.

...