Ошибка времени жизни при создании функции, которая возвращает значение, реализующее serde::Deserialize
Я использую serde и serde_json 1.0 для декодирования данных из строки base64:
fn from_base64_str<T: Deserialize>(string: &str) -> T {
let slice = decode_config(string, URL_SAFE).unwrap();
serde_json::from_slice(&slice).unwrap()
}
Когда я собираю, я получил это:
error[E0106]: missing lifetime specifier
--> src/main.rs:6:23
|
6 | fn from_base64_str<T: Deserialize>(string: &str) -> T {
| ^^^^^^^^^^^ expected lifetime parameter
Проверяя serde doc, Deserialize
определяется как:
pub trait Deserialize<'de>: Sized {
Поэтому я добавил время жизни:
fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
let slice = decode_config(string, URL_SAFE).unwrap();
serde_json::from_slice(&slice).unwrap()
}
Затем компилятор сказал мне:
error: `slice` does not live long enough
--> src/main.rs:11:29
|
11 | serde_json::from_slice(&slice).unwrap()
| ^^^^^ does not live long enough
12 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'de as defined on the body at 9:64...
--> src/main.rs:9:65
|
9 | fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
| _________________________________________________________________^ starting here...
10 | | let slice = decode_config(string, URL_SAFE).unwrap();
11 | | serde_json::from_slice(&slice).unwrap()
12 | | }
| |_^ ...ending here
Я знаю только самые основы жизни в Rust, поэтому меня очень смущает 'de
в trait Deserialize
,
Как я могу исправить ошибку времени жизни в такой функции? Я использую Rust 1.18.0-nightly (452bf0852 2017-04-19)
2 ответа
Я нашел ответ от вопроса 891 Серде: я должен использовать DeserializeOwned
вместо Deserialize
,
Этот раздел сайта Serde охватывает Deserialize
границы в деталях.
Есть два основных способа написания Deserialize
границы черты, будь то в блоке impl или функции или где-либо еще.
<'de, T> where T: Deserialize<'de>
Это означает, что "T может быть десериализован с некоторой жизни". Звонящий решает, что это за жизнь. Обычно это используется, когда вызывающая сторона также предоставляет данные, из которых выполняется десериализация, например, в такой функции, как
serde_json::from_str
, В этом случае входные данные также должны иметь время жизни'de
Например, это может быть&'de str
,<T> where T: DeserializeOwned
Это означает, что "T может быть десериализован из любой жизни". Вызываемый должен решить, какая жизнь. Обычно это происходит потому, что данные, из которых выполняется десериализация, будут выброшены до того, как функция вернется, поэтому нельзя допускать, чтобы T заимствовал из нее. Например, функция, которая принимает закодированные в base64 данные в качестве входных данных, декодирует их из base64, десериализует значение типа T, а затем отбрасывает результат декодирования base64. Другое распространенное использование этой границы - функции, которые десериализуются из потока ввода-вывода, такие как
serde_json::from_reader
,Чтобы сказать это более технически,
DeserializeOwned
признак эквивалентен признаку признака более высокого рангаfor<'de> Deserialize<'de>
, Единственная разницаDeserializeOwned
более интуитивно понятен для чтения. Это означает, что T владеет всеми данными, которые десериализуются.