I'm having trouble understanding the relationship between the lifetimes on this code. Basically, I have a Rocket API that receives some x-www-form-urlencoded
data, with only one key: json
. This key contains, intuitively, a JSON value, encoded with percent-encoding, of a struct Message<T>
.
(I'm aware this is suboptimal API design, but this is reverse-engineering work, so I have no option)
To be easily used as a request guard as From<Message<T>>
, I'm implementing FromForm
. To do that, I need to implement FromForm<'f>
for any Message<T>
where T
implements Deserialize<'de>
. I wrote my impl signature as impl<'f, 'de, T> FromForm<'f> for Message<T> where T: Deserialize<'de>
.
To actually perform the decoding, I:
- Get the
"json"
key of the form data;
- URL-decode the value;
- Parse the JSON contained in the value.
Bailing out as soon as possible. Code doing that (explicit type annotations for the reader's convenience):
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 in a paste-and-run way (doesn't work on the Playground since it depends on Rocket).
As I understand:
- The
&RawStr
of encoded
has lifetime 'f
.
- A
String
is created out of it by url_decode
, which lives until the end of the function
serde_json
takes a &'x str
where 'x
does not need to coincide with 'de
, and returns a value (so it lives to the end of the function, and since it's returned, gets moved beyond it)
But it seems my understanding is incorrect:
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 | | }
| |_^
What am I getting wrong, and how can I return the deserialized value properly?
See Question&Answers more detail:
os