我正在尝试编写一个允许对任意(反)可序列化结构进行gzip编码/解码的特性。我的主要用例是通过一个干净的API在磁盘上持久化一些有状态的结构。为此,每当struct S实现serde的Serialize和Deserialize (我们的特性在范围内)时,它的压缩+序列化副本应该由/写到任何有需求的Read/Write。
例如:
描述某些(反)可序列化结构的读/写API的特性。
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::Read和std::io::Write )实现std::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.
}
}一个示例有状态结构,它(De)可由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缺乏终身注释。Serde有一个关于反序列化生存期的漂亮的写起来。
我组装了一个游乐场,试图解决生命周期问题,通过这样做,我遇到了另一个编译器错误(*),在这种情况下,这对我来说似乎很奇怪。
我真的很困惑我到底是在哪一点上走错了路,以及如何纠正它。如果有人能帮助我理解我在这个实现中所犯的错误,以及如何防止它再次发生,我将非常感激。
发布于 2022-04-18 08:44:55
如果将DeserializeOwned用作绑定而不是Deserialize<'de>,则代码将进行编译。
塞德的生命之页对DeserializeOwned有这样的看法(由我重点介绍):
这意味着"T可以从任何生命周期反序列化“。被叫的人可以决定一生的长短。通常是因为被反序列化的数据将在函数返回之前被丢弃,所以不能允许T借用它。例如,一个接受base64 64编码的数据作为输入的函数,从base64解码它,反序列化一个T类型的值,然后丢弃base64解码的结果。..。
这与您的用例完全匹配,因为buf是在函数返回之前删除的。
https://stackoverflow.com/questions/71909265
复制相似问题