Невозможно выйти из заемного контента, без заемного контента
Я работаю над созданием REST API с использованием Rust и Rocket. У меня есть конечная точка, в которой я создаю нового пользователя, определенного следующим образом:
/// View with which to create a user
#[post("/users", format = "application/json", data = "<user_data>")]
fn create_user(user_data: Json<UserData>, db: DB) -> Status<Json<Value>> {
let conn = db.conn();
let _new_user_result = user_data.into_new_user(&conn);
unimplemented!()
}
Обратите внимание, что здесь нет заимствованного контента; и то и другое user_data
а также db
являются собственностью Тем не менее, я получаю следующую ошибку при компиляции:
error[E0507]: cannot move out of borrowed content
--> src/views/user_account.rs:75:28
|
75 | let _new_user_result = user_data.into_new_user(&conn);
| ^^^^^^^^^ cannot move out of borrowed content
Для справки, функция подписи into_new_user
является
fn into_new_user(self, conn: &SqliteConnection) -> Result<NewUser, Status<Json<Value>>> {
...
}
Что здесь происходит? Эту ошибку было бы намного легче понять, если бы я на самом деле что-то заимствовал, но, учитывая, что я владею всем этим вопросом, я сбит с толку.
$ rustc --version; cargo --version
rustc 1.22.0-nightly (a47c9f870 2017-10-11)
cargo 0.23.0-nightly (e447ac7e9 2017-09-27)
1 ответ
Проблема здесь была с типом user_data
, В частности, именно так, как написано в сигнатуре функции, ее тип Json<UserData>
,
Json<T>
тип обертки, который сообщает Rocket, как обернуть и развернуть значения JSON; это удобный метод, который оборачивает вашу структуру, но не хранит никаких дополнительных данных. Поэтому он реализует Deref<Target = T>
, что позволяет вам в основном игнорировать это. Однако это работает только тогда, когда вы не пытаетесь потреблять его.
Типы, которые реализуют Deref<Target=T>
обычно можно использовать так, как если бы они были T
; компилятор обрабатывает перенаправление для вас. Однако то, что на самом деле происходит в этом вызове функции, является чем-то вроде <Json<UserData> as Deref<Target=UserData>>::deref().into_new_user();
и вот где проблема возникает: deref
определяется как fn deref(&self) -> &Self::Target
, Заимствование происходит неявно и незаметно, но оно есть.
Json
тип больше не нужен в этом случае; это только для десериализации UserData
структура. Поэтому мы можем решить проблему, отбросив ее. Json::into_inner
метод отбрасывает Json
обертка, давая вам в собственность UserData
, Это может тогда потребляться как запланировано. В совокупности функция должна выглядеть так:
fn create_user(user_data: Json<UserData>, db: DB) -> Status<Json<Value>> {
let conn = db.conn();
let _new_user_result = user_data.into_inner().into_new_user(&conn);
unimplemented!()
}