问题描述
我正在为一个项目编写一个反序列化器(Vec<u8>
(原始 JSON)到任何类型 T)并尝试使用 serde。这是我解码数据的特征:
pub trait Decode: Sized {
fn try_decode(input: Vec<u8>) -> Result<Self,InternalError>;
}
因为我打算在我的结构上使用 #[derive(Deserialize)]
,所以我正在为实现具有任意生命周期的 Deserialize trait 的任何类型编写一个实现:
impl<'a,T: Deserialize<'a>> Decode for T {
fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
if let Ok(t) = serde_json::from_slice(&input) {
Ok(t)
} else {
Err(Internal::decode("Could not decode"))
}
}
}
error[E0597]: `input` does not live long enough
--> src/decode.rs:16:47
|
14 | impl<'a,T: Deserialize<'a>> Decode for T {
| -- lifetime `'a` defined here
15 | fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
16 | if let Ok(t) = serde_json::from_slice(&input) {
| -----------------------^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `input` is borrowed for `'a`
...
21 | }
| - `input` dropped here while still borrowed
我理解编译器为什么生我的气。在检查 from_slice 的实现后,我认为它具有相关的生命周期。我确信输入是一个拥有的值,但是 from_slice 需要一个引用,所以在这里我返回一个值的引用,该值在函数结束时被删除,这显然是不正确的。我的问题是,有没有办法确保在 生命周期(即此函数的调用者提供的生命周期)内借用该值。我无法更新特征,因为它会导致灾难。
解决方法
如果你想要一个不从切片借用的值,你可以使用 DeserializeOwned 作为 trait bound,它没有关联的生命周期(因此只存储拥有的值)。例如,这会编译:
impl<T: DeserializeOwned> Decode for T {
fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
if let Ok(t) = serde_json::from_slice(&input) {
Ok(t)
} else {
todo!()
}
}
}
,
使用具有生命周期的反序列化的正确方法是使用 Higher Rank Trait Bounds:使用 for<'a>
表示法专门告诉编译器此生命周期对所有(相关的)生命周期都有效。代码将如下所示:
impl<T: for<'de> Deserialize<'de>> InputCoercible for T {
// ...trait methods...
}