首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >拥有的变量似乎不会发出只要serde反序列化生命周期所需的生存期的借款。

拥有的变量似乎不会发出只要serde反序列化生命周期所需的生存期的借款。
EN

Stack Overflow用户
提问于 2022-04-18 08:14:33
回答 1查看 115关注 0票数 -1

我正在尝试编写一个允许对任意(反)可序列化结构进行gzip编码/解码的特性。我的主要用例是通过一个干净的API在磁盘上持久化一些有状态的结构。为此,每当struct S实现serdeSerializeDeserialize (我们的特性在范围内)时,它的压缩+序列化副本应该由/写到任何有需求的Read/Write

例如:

描述某些(反)可序列化结构的读/写API的特性。

代码语言:javascript
运行
复制
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 )实现std::io::Write

代码语言:javascript
运行
复制
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宏序列化。

代码语言:javascript
运行
复制
// 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。

代码语言:javascript
运行
复制
// 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有一个关于反序列化生存期的漂亮的写起来

我组装了一个游乐场,试图解决生命周期问题,通过这样做,我遇到了另一个编译器错误(*),在这种情况下,这对我来说似乎很奇怪。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-18 08:44:55

如果将DeserializeOwned用作绑定而不是Deserialize<'de>,则代码将进行编译。

塞德的生命之页DeserializeOwned有这样的看法(由我重点介绍):

这意味着"T可以从任何生命周期反序列化“。被叫的人可以决定一生的长短。通常是因为被反序列化的数据将在函数返回之前被丢弃,所以不能允许T借用它。例如,一个接受base64 64编码的数据作为输入的函数,从base64解码它,反序列化一个T类型的值,然后丢弃base64解码的结果。..。

这与您的用例完全匹配,因为buf是在函数返回之前删除的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71909265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档