当尝试解决复杂的编程问题时,删除尽可能多的内容非常有用。获取您的代码并删除您可以删除的内容,直到问题消失。稍微调整一下你的代码并继续删除,直到你不能再删除为止。然后,扭转问题,从最小的部分开始构建,并返回到错误处。执行这两项操作将告诉您问题出在哪里。
首先,让我们确保我们正确地反序列化:
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use std::borrow::Cow;
#[derive(Debug, Deserialize)]
pub struct Example<'a> {
#[serde(borrow)]
name: Cow<'a, str>,
key: bool,
}
impl<'a> Example<'a> {
fn info(&self) {
println!("{:?}", self);
match self.name {
Cow::Borrowed(_) => println!("Is borrowed"),
Cow::Owned(_) => println!("Is owned"),
}
}
}
fn main() {
let data: Vec<_> = br#"{"key": true, "name": "alice"}"#.to_vec();
let decoded: Example = serde_json::from_slice(&data).expect("Couldn't deserialize");
decoded.info();
}
在这里,我忘记添加#[serde(borrow)]
属性,所以我很高兴我做了这个测试!
接下来我们就来介绍一下租赁箱:
#[macro_use]
extern crate rental;
rental! {
mod holding {
use super::*;
#[rental]
pub struct VecHolder {
data: Vec<u8>,
parsed: Example<'data>,
}
}
}
fn main() {
let data: Vec<_> = br#"{"key": true, "name": "alice"}"#.to_vec();
let holder = holding::VecHolder::try_new(data, |data| {
serde_json::from_slice(data)
});
let holder = match holder {
Ok(holder) => holder,
Err(_) => panic!("Unable to construct rental"),
};
holder.rent(|example| example.info());
// Make sure we can move the data and it's still valid
let holder2 = { holder };
holder2.rent(|example| example.info());
}
接下来我们尝试创建一个租赁Chunk
:
#[rental]
pub struct ChunkHolder {
data: Chunk,
parsed: Example<'data>,
}
不幸的是,这失败了:
--> src/main.rs:29:1
|
29 | rental! {
| ^
|
= help: message: Field `data` must have an angle-bracketed type parameter or be `String`.
哎呀!检查租赁文件,我们可以添加#[target_ty_hack="[u8]"]
to the data
场地。这导致:
error[E0277]: the trait bound `hyper::Chunk: rental::__rental_prelude::StableDeref` is not satisfied
--> src/main.rs:29:1
|
29 | rental! {
| ^ the trait `rental::__rental_prelude::StableDeref` is not implemented for `hyper::Chunk`
|
= note: required by `rental::__rental_prelude::static_assert_stable_deref`
这很烦人;因为我们无法实现该特征Chunk
,我们只需要装箱Chunk
,证明它有一个稳定的地址:
#[rental]
pub struct ChunkHolder {
data: Box<Chunk>,
parsed: Example<'data>,
}
我还想看看是否有办法获得Vec<u8>
退出Chunk
,但它似乎不存在。这将是另一种分配和间接较少的解决方案。
此时,剩下的“所有”就是将其集成回 futures 代码中。除了你之外,任何人都需要做大量的工作来重新创建它,但我预计这样做不会出现任何明显的问题。