【发布时间】:2018-01-28 17:08:34
【问题描述】:
我无法理解这段代码的生命周期之间的关系。基本上,我有一个 Rocket API,它接收一些 x-www-form-urlencoded 数据,只有一个键:json。直观地说,这个键包含一个 JSON 值,用百分比编码编码,结构 Message<T>。
(我知道这是次优的 API 设计,但这是逆向工程工作,所以我别无选择)
为了像From<Message<T>> 一样轻松用作请求保护,我正在实现FromForm。为此,我需要为任何Message<T> 实现FromForm<'f>,其中T 实现Deserialize<'de>。我将我的 impl 签名写为impl<'f, 'de, T> FromForm<'f> for Message<T> where T: Deserialize<'de>。
要实际执行解码,我:
- 获取表单数据的
"json"键; - 对值进行 URL 解码;
- 解析值中包含的 JSON。
尽快退出。执行此操作的代码(为方便读者使用显式类型注释):
fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<Self, Self::Error> {
// Get JSON field
let encoded: Option<&RawStr> = items.find(|&(k, _)| k.as_str() == "json")
.map(|(_, v)| v);
if let None = encoded {
return Err(MessageFormError::MissingJsonKey);
}
// Decode URL-string
let decoded: Result<String, Utf8Error> = encoded.unwrap().url_decode();
if let Err(e) = decoded {
return Err(MessageFormError::InvalidUrl(e));
}
// Parse JSON
let json: String = decoded.unwrap();
serde_json::from_str::<Self>(&json) // Line 205
.map_err(|e| MessageFormError::InvalidJson(e))
}
A Gist demonstrating the problem 以粘贴运行的方式(不适用于 Playground,因为它依赖于 Rocket)。
据我了解:
-
encoded的&RawStr具有生命周期'f。 -
String是由url_decode用它创建的,它一直存在到函数结束 -
serde_json接受&'x str,其中'x不需要与'de重合,并返回一个值(因此它一直存在到函数的末尾,并且由于它被返回,因此被移到它之外)
但看来我的理解是错误的:
205 | serde_json::from_str::<Self>(&json)
| ^^^^ does not live long enough
206 | .map_err(|e| MessageFormError::InvalidJson(e))
207 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'f as defined on the impl at 184:1...
--> src/transport.rs:184:1
|
184 | / impl<'f, T> FromForm<'f> for Message<T>
185 | | where T: Deserialize<'f>
186 | | {
187 | | type Error = MessageFormError;
... |
207 | | }
208 | | }
| |_^
我做错了什么,如何正确返回反序列化的值?
【问题讨论】:
-
能不能把代码放在playground里,方便转载?乍一看,
'f和'de的生命周期之间似乎存在缺失关系。 -
@E_net4 不完全是,因为操场上没有 Rocket 板条箱,很遗憾。我会做一个更完整的例子,可以粘贴到文件中。
-
@E_net4 添加了要点!
标签: rust serde rust-rocket