长度未知的 Serde serialize_seq

Serde serialize_seq with unknown len

serialize_seq 的文档指出

Begin to serialize a variably sized sequence. This call must be followed by zero or more calls to serialize_element, then a call to end.

The argument is the number of elements in the sequence, which may or may not be computable before the sequence is iterated. Some serializers only support sequences whose length is known up front.

我想在迭代序列之前序列化一个长度未知的序列。

他们给出的简单例子是:

use serde::ser::{Serialize, Serializer, SerializeSeq};

impl<T> Serialize for Vec<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
        for element in self {
            seq.serialize_element(element)?;
        }
        seq.end()
    }
}

如何修改上面的代码以支持在迭代序列之前无法计算的长度?

也许我误解了文档,但我希望类似的东西能起作用:

use serde::ser::{Serialize, Serializer, SerializeSeq};

impl<T> Serialize for Vec<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut lazy_len = 0
        let mut seq = serializer.serialize_seq(Some(lazy_len))?;
        for element in self {
            lazy_len += 2;
            seq.serialize_element(element)?;
        }
        seq.end()
    }
}

这将给出两倍的序列长度。

长度参数是一个 Option<usize> 因为你可能有也可能没有。你没有,所以使用 None 而不是 Some.

let mut seq = serializer.serialize_seq(None)?;

正如注释所说,一些序列化程序需要长度,而另一些则不需要。 序列化程序将使用您传递给 serialize_seq 的值来(例如)立即 分配缓冲区。他们通过执行一次然后将每个元素序列化到该内存中来获得更好的性能。扩展每个项目的长度根本没有好处,因为它们每次也需要扩展缓冲区,如果你传递 None 作为长度,它们就会这样做。

这应该适用于 Json,但如果没有它,一些其他更高效的格式(如 Bincode)可能会拒绝序列化。特别是,某些编码格式会将长度序列化为值之前格式的一部分。

Maybe I have misunderstood the documentation, but I would expect something similar to this to work:

...
let mut lazy_len = 0
let mut seq = serializer.serialize_seq(Some(lazy_len))?;
for element in self {
    lazy_len += 2;
    seq.serialize_element(element)?;
}
...

整数是 Copy 类型,所以 serializer.serialize_seq(Some(lazy_len)) 只是复制 lazy_len 的值,之后修改 lazy_len 将没有任何效果。