如何反序列化包含结构向量的枚举变体?

How to deserialize an enum variant containing a vector of structs?

我对使用 Rust 还是很陌生,生命周期仍然让我感到困惑。我正在尝试让这样的简化代码工作:

#[derive(Debug, Serialize, Deserialize)]
pub struct MyStruct<'a> {
    str_field: &'a str,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum MyEnum<'a> {
    // This compiles
    #[serde(borrow)]
    MyStructField(MyStruct<'a>),
    
    // This does not compile
    #[serde(borrow)]
    MyStructVecField(Vec<&'a MyStruct<'a>>),
}


fn main() {
    println!("Hello World");
}

这是错误信息:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `&'a MyStruct<'a>: Deserialize<'_>` is not satisfied
    --> src/main.rs:16:22
     |
16   |     MyStructVecField(Vec<&'a MyStruct<'a>>),
     |                      ^^^ the trait `Deserialize<'_>` is not implemented for `&'a MyStruct<'a>`
     |
     = help: the following implementations were found:
               <MyStruct<'a> as Deserialize<'de>>
     = note: required because of the requirements on the impl of `Deserialize<'_>` for `Vec<&'a MyStruct<'a>>`
note: required by a bound in `newtype_variant`
    --> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.136/src/de/mod.rs:2118:12
     |
2118 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `newtype_variant`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

我确实找到了serde deserializer lifetimes 文档,但我没有牢牢掌握它,至少没有很好地解决我的问题。我不太确定我必须做什么才能让它工作。我可以使用派生使其工作吗?我是否必须编写自定义反序列化实现?它可以工作吗?解释清楚问题加分。

Rust Playground link

您正在尝试反序列化引用。然而,从本质上讲,引用指向存储在别处的数据。这适用于 &str&[u8],因为它们只是 fat-pointers 到原始字节,并且可以只引用它们被反序列化的数据。然而,这也意味着输出类型将取决于输入数据的生命周期。通常这很好,因为我们可以执行 zero-copy 反序列化。 #[serde(borrow)] 充当了一些样板文件,因此它可以在实现特征时获得正确的生命周期要求。

但是,MyStruct<'a>不一样。它不存在于输入数据中,因此必须在反序列化期间创建。如果我们想反序列化对它的引用,这会导致问题。 MyStruct<'a> 输入中不存在,堆栈上的值也没有足够长的时间。

幸运的是,这有一个简单的修复方法。只需使用拥有的价值。这仍然算作 zero-copy 反序列化,因为一开始没有什么可复制的。

#[derive(Debug, Serialize, Deserialize)]
pub enum MyEnum<'a> {
    #[serde(borrow)]
    MyStructField(MyStruct<'a>),
    #[serde(borrow)]
    MyStructVecField(Vec<MyStruct<'a>>),
}

Vec 与问题无关。 MyStructField(&'a MyStruct<'a>) 同样无效,会产生同样的错误。