如何反序列化包含结构向量的枚举变体?
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 文档,但我没有牢牢掌握它,至少没有很好地解决我的问题。我不太确定我必须做什么才能让它工作。我可以使用派生使其工作吗?我是否必须编写自定义反序列化实现?它可以工作吗?解释清楚问题加分。
您正在尝试反序列化引用。然而,从本质上讲,引用指向存储在别处的数据。这适用于 &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>)
同样无效,会产生同样的错误。
我对使用 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 文档,但我没有牢牢掌握它,至少没有很好地解决我的问题。我不太确定我必须做什么才能让它工作。我可以使用派生使其工作吗?我是否必须编写自定义反序列化实现?它可以工作吗?解释清楚问题加分。
您正在尝试反序列化引用。然而,从本质上讲,引用指向存储在别处的数据。这适用于 &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>)
同样无效,会产生同样的错误。