rust - Lifetimes when Deserializing JSON within a FromForm -


i'm having trouble understanding relationship between lifetimes on code. basically, have rocket api receives x-www-form-urlencoded data, 1 key: json. key contains, intuitively, json value, encoded percent-encoding, of struct message<t>.

(i'm aware suboptimal api design, reverse-engineering work, have no option)

to used request guard from<message<t>>, i'm implementing fromform. that, need implement fromform<'f> message<t> t implements deserialize<'de>. wrote impl signature impl<'f, 'de, t> fromform<'f> message<t> t: deserialize<'de>.

to perform decoding, i:

  1. get "json" key of form data;
  2. url-decode value;
  3. parse json contained in value.

bailing out possible. code doing (explicit type annotations reader's convenience):

fn from_form(items: &mut formitems<'f>, strict: bool) -> result<self, self::error> {     // 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 problem in paste-and-run way (doesn't work on playground since depends on rocket).

as understand:

  • the &rawstr of encoded has lifetime 'f.
  • a string created out of url_decode, lives until end of function
  • serde_json takes &'x str 'x not need coincide 'de, , returns value (so lives end of function, , since it's returned, gets moved beyond it)

but seems understanding incorrect:

205 |         serde_json::from_str::<self>(&json)     |                                       ^^^^ not live long enough 206 |             .map_err(|e| messageformerror::invalidjson(e)) 207 |     }     |     - borrowed value lives until here     | note: borrowed value must valid lifetime 'f defined on impl @ 184:1...    --> src/transport.rs:184:1     | 184 | / impl<'f, t> fromform<'f> message<t> 185 | |     t: deserialize<'f> 186 | | { 187 | |     type error = messageformerror; ...   | 207 | |     } 208 | | }     | |_^ 

what getting wrong, , how can return deserialized value properly?

this section of serde website covers deserialize bounds in detail.


there 2 main ways write deserialize trait bounds, whether on impl block or function or anywhere else.

  • <'de, t> t: deserialize<'de>

    this means "t can deserialized some lifetime." caller gets decide lifetime is. typically used when caller provides data being deserialized from, example in function serde_json::from_str. in case input data must have lifetime 'de, example &'de str.

  • <t> t: deserializeowned

    this means "t can deserialized any lifetime." callee gets decide lifetime. because data being deserialized going thrown away before function returns, t must not allowed borrow it. in case data coming url-decoding input, , decoded data thrown away after deserializing t. common use of bound functions deserialize io stream, such serde_json::from_reader.

    to more technically, deserializeowned trait equivalent higher-rank trait bound for<'de> deserialize<'de>. difference deserializeowned more intuitive read. means t owns data gets deserialized.

replacing t: deserialize<'f> bound t: deserializeowned correctly communicates t not allowed borrow url-decoded data because url-decoded data not outlive t.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -