Owned变量似乎没有发出服务反序列化生命周期所要求的借用



我正在尝试编写一个允许任意(反)可序列化结构的gzip编码/解码的特性。我的主要用例是通过一个干净的API在磁盘上持久化一些有状态结构。为此,任何时候结构体S实现serdeSerializeDeserialize,并且我们的trait在范围内,它的gzip +序列化副本应该根据需要由Read/Write读取/写入。

例如:

描述读/写(反)序列化结构体的API的trait。

use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use serde::{Serialize, Deserialize};
use rmp_serde::{Serializer};
use std::io::{Read, Write};
pub type Result<T, E = std::io::Error> = std::result::Result<T, E>;
pub trait ReadWriteState<S: Serialize + Deserialize> {
/// Write the given persistent state to a stream.
fn write_state(&mut self, state: &S) -> Result<usize>;
/// Write the given persistent state to a stream.
fn read_state(&mut self) -> Result<S>;
}

对可(反)序列化状态的ReadWriteState的全面实现,并通过同时为std::io::Readstd::io::Write的任何东西。

impl<S, T> ReadWriteState<S> for T 
where
S: Serialize + Deserialize, // This doesn't work because of lifetimes in serde Deserializer.
T: Read + Write
{
/// Serialize the state into messagepack and then
/// GzEncode it before sending to the output stream.
fn write_state(&mut self, state: &S) -> Result<usize> {
let mut buf = Vec::new();
state
.serialize(&mut Serializer::new(&mut buf))
.unwrap_or_else(|_| panic!("Could not serialize data."));
let mut e = GzEncoder::new(Vec::new(), Compression::default());
e.write_all(&buf)?;
let compressed_bytes = e.finish()?;
let length = compressed_bytes.len();
self.write_all(&compressed_bytes)?;
}
/// Decode the gzipped stream into msgpack and then further deserialize it into the generic state struct.
fn read_state(&mut self) -> Result<S, serde_json::Error> {
let mut decoder = GzDecoder::new(self);
let mut buf = Vec::new(); // The buf is created here so it is owned by this function scope.
decoder.read_to_end(&mut buf).expect("Couldn't read the gzipped stream to end.");
serde_json::from_slice::<'de, S>(&buf) // (*)
// This is what I expect should work fine 
// but the borrow checker complains that 
// `buf` doesn't live long enough.
}
}

一个可以被serde_derive宏(反)序列化的有状态结构的示例。

// Now suppose we have some struct that is Serialize as
// well as Deserialize.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct FooMap<K, V> 
where
// For a moment, suppose Deserialize doesn't need a lifetime.
// To compile, it should look more like Deserialize<'a> for some defined
// lifetime 'a, but let's ignore that for a moment.
K: Clone + Hash + Eq + Serialize + Deserialize,
V: Eq + Serialize + Deserialize
{
pub key: K,
pub value: V
}

FooMap提供的方便的磁盘持久性API。

// Now I should be able to write gzipped + messagepacked FooMap to file.
pub fn main() {
let foomap = FooMap {
key: "color",
value: "blue"
};
let mut file = std::fs::File::create("/tmp/foomap.gz").expect("Could not create file.");
let bytes_written = file.write_state(&foomap).expect("Could not write state.");
println!("{} bytes written to /tmp/foomap.gz", bytes_written);
let mut file = std::fs::File::open("/tmp/foomap.gz").expect("Could not open file.");
let recovered: FooMap<&str, &str> = file.read_state().expect("Could not recover FooMap.");
assert_eq!(foomap, recovered);
}

您可能会注意到上面代码中的一些问题。我所知道的是Deserialize在用作trait绑定时缺乏生命周期注释。Serde有一篇关于反序列化生命周期的漂亮文章。

我已经把一个Playground放在一起,试图解决生命周期问题,通过这样做,我遇到了另一个编译错误(*),在这种情况下,对我来说似乎很奇怪。

我真的很困惑,我到底是在什么时候走错了路,以及如何纠正它。如果有人能帮助我了解我在这个实现中犯的错误,以及我如何防止它再次发生,我将非常感激。

如果您使用DeserializeOwned而不是Deserialize<'de>作为绑定,则代码可以编译。

serde的生命周期页面是这样说DeserializeOwned的(我的亮点):

这意味着"T可以从任何生命周期反序列化"。被调用者可以决定什么生命周期。通常这是因为要反序列化的数据将在函数返回之前被丢弃,所以T必须不允许从它那里借用。例如,一个函数接受base64编码的数据作为输入,从base64解码,反序列化类型为T的值,然后丢弃base64解码的结果。[…]

这完全符合您的用例,因为buf在函数返回之前被删除。

最新更新