2017-08-20 23 views
1

このコードの有効期間の間の関係を理解できません。基本的には、という1つのキーを持つx-www-form-urlencodedデータを受け取るRocket APIがあります。このキーには直感的にパーセントコードでエンコードされた構造体Message<T>のJSON値が含まれています。FromForm内でJSONを逆シリアル化するライフタイム

は簡単に私がFromFormを実装しています、From<Message<T>>よう要求ガードとして使用するために(私は、これは次善のAPIの設計であるが、これはリバースエンジニアリングを仕事であるので、私は何のオプションが用意されていません注意してくださいね)。そのためにはMessage<T>にはFromForm<'f>を実装する必要があります。ここで、TDeserialize<'de>です。私はimpl<'f, 'de, T> FromForm<'f> for Message<T> where T: Deserialize<'de>と私のインプラントの署名を書いた。実際にデコードを実行するには

、I:

  1. フォームデータの"json"キーを取得します。
  2. URLデコードの値。
  3. 値に含まれる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

私が理解したよう:

  • encoded&RawStrは寿命'fを持っています。
  • Stringが機能
  • serde_jsonの端部が'xは、'deと一致する必要はない&'x strをとり、その値を返す(それはの終わりに住んまで住んでいる、url_decodeによってそれから作成されますそれが返されるので、関数は、および、

)、それを超えて移動します。しかし、それは私の理解が間違っているようだ:

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 | | } 
    | |_^ 

Whを私が間違っていると、どのように私は正しくdeserialized値を返すことができますか?

+0

よりも長生きしないので、Tが URLデコードデータから借りることは許されないことを通信します置くことができます[playground](https://play.rust-lang.com)のコードを簡単に再現できるようにしますか?一見すると、生涯「f」と「de」との間には、欠けている関係があるようです。 –

+0

@ E_net4遊び場にはロケットの箱がないので、悲しいことです。私はファイルに貼り付けることができるより完全な例を作ります。 – Kroltan

+0

@ E_net4 gist!が追加されました! – Kroltan

答えて

2

This section of the Serde website covers Deserialize bounds in detail.


IMPLブロックまたはどこか他の関数または上 か、Deserialize形質境界を書くには、2つの主要な方法があります。

  • <'de, T> where T: Deserialize<'de>

    これは、 "Tが一部寿命から非直列化することができます。" という意味呼び出し元は、それがどの生涯であるかを判断します。通常、これは、 のように、たとえば serde_json::from_strのような関数から、呼び出し元がデシリアライズされるデータを提供する場合に使用されます( )。 この場合、入力データの有効期間は'deでなければなりません。たとえば、 の場合、&'de strとなります。

  • <T> where T: DeserializeOwned

    これは、 "Tがから任意の寿命を非直列化することができます。" という意味被告人はどの生涯を決定するようになる。通常、これは、 がデシリアライズされているデータが 関数が返される前に破棄されるため、Tがそこから借りることを許されてはならないからです。データは、URLデコードし、いくつかの入力から来ている、とデコード データをバインドこの のもう一つの一般的な使用は、 serde_json::from_readerなどIOストリームからデシリアライズ機能、であるT.をデシリアライズした後に捨てている。あなたの 場合もっと技術的にそれを言う

    DeserializeOwned トレイトはhigher-rank trait bound for<'de> Deserialize<'de>と同等です。唯一の違いはDeserializeOwnedです。 は直感的です。これは、Tがデシリアライズされた を取得するすべてのデータを所有していることを意味します。

T: DeserializeOwned が結合したあなたのT: Deserialize<'f>を交換すると、正しくURLデコードデータはT.

+0

ああ、今私は理解している。入力が出力よりも長くなければならないということは意味があります。寿命がリファレンスだけからどのように結びついたのか分かりませんでした。しかし、私はShepmasterに同意する必要があります。質問にインラインで答えてください。 – Kroltan