当必须知道序列长度和类型时,在 Serde 中序列化序列?

Serializing a sequence in Serde when both sequence length and types must be known?

我正在用 Rust 开发一个 Serde 序列化程序,用于 JSON 类二进制格式。

它根据每个元素的大小是否相同,或者是否是混合元素大小的序列,对序列使用不同的二进制编码。

例如:

根据我对 Serde 的了解,它一次序列化一个元素的序列,并且在序列序列化开始时(通过调用 serialize_seq on a Serializer)只有序列长度是可选的。

是否有一个很好的模式来处理上述情况,在检查所有元素(并序列化以了解它们的字节长度)之前不能序列化序列?它还需要处理嵌套序列,如上例所示。

使用 mcarton 关于在序列序列化程序中存储元素的建议解决了问题。

这会将每个序列化的字节序列存储在 Vec 中(即作为 Vec<Vec<u8>>),并在序列化为 output 之前检查所有项目的长度是否相等。

这看起来像:

/// Main top level serializer.
pub struct Serializer {
    output: Vec<u8>
}

impl<'a> ser::Serializer for &'a mut Serializer {
    // ... skipped ...

    type SerializeSeq = ArraySerializer<'a>;

    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
        let array_ser = ArraySerializer {
            items: Vec::new(),
            output: &mut self.output,
        };
        Ok(array_ser)
    }

    // ... skipped ...
}


pub struct ArraySerializer<'a> {
    /// Temporary storage for individual serialized array elements.
    items: Vec<Vec<u8>>,

    /// Storage for final serialized output of header plus all elements. This is
    /// typically a reference to the full output buffer being serialized into.
    output: &'a mut Vec<u8>,
}

impl <'a> ser::SerializeSeq for ArraySerializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<Self::Ok> where
        T: ?Sized + Serialize {
        // default serializer used for serializing array elements
        let mut serializer = Serializer::default();

        // serialize individual item and add to `items`
        value.serialize(&mut serializer)?;
        self.items.push(serializer.output);
        Ok(())
    }

    fn end(self) -> Result<Self::Ok> {
        if self.items.is_empty() {
            self.output.push(EMPTY_ARRAY_HEADER);
            return Ok(());
        }

        let all_elems_same_length = self.items
            .iter()
            .all(|ref v| v.len() == self.items[0].len());
        };

        if all_elems_same_length {
            self.output.push(SAME_LENGTH_HEADER);
            for item in &mut self.items.iter_mut() {
                self.output.append(item);
            }
        } else {
            self.output.push(VARIABLE_LENGTH_HEADER);

            // ... skipped: encode rest of items using more complicated serialization ...
        }

        Ok(())
    }
}