このコードのライフタイム間の関係を理解するのに苦労しています。x-www-form-urlencoded
基本的に、キーが 1 つだけのデータを受け取る Rocket API がありますjson
。このキーには、直観的に、パーセントエンコーディングでエンコードされた struct の JSON 値が含まれていますMessage<T>
。
(これが次善の API 設計であることは承知していますが、これはリバース エンジニアリング作業であるため、選択の余地はありません)
として簡単にリクエストガードとして使えるようにFrom<Message<T>>
、 を実装してFromForm
います。そのためには、FromForm<'f>
あらゆるMessage<T>
場所に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))
}
貼り付けて実行する方法で問題を示す Gist (Playground は Rocket に依存しているため、Playground では機能しません)。
私が理解しているように:
&RawStr
of にencoded
はライフタイムがあります'f
。- A
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 | | }
| |_^
何が間違っているのですか?どうすればデシリアライズされた値を適切に返すことができますか?