gpt4 book ai didi

rust - Serde::Deserialize 的实现不够通用

转载 作者:行者123 更新时间:2023-12-05 03:40:22 29 4
gpt4 key购买 nike

我正在使用 event_emmiter_rs用于我的应用程序中的事件处理。该库允许您订阅带有回调的事件并触发这些事件。事件采用 (strings, value) 的形式,回调采用接受值参数的闭包形式。通过事件回调发送的值必须实现 Serde::Deserialize。 We can see this here in the docs .所以我创建了这个简单的设置:

use event_emitter_rs::EventEmitter;
use serde::Serialize;
use serde::Deserialize;
use std::borrow::Cow;

#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(bound(deserialize = "'de: 'static"))]
//#[serde(bound(deserialize = "'de: 'a"))] using the 'a lifetime gives same error
pub struct DraggableInfo<'a>{
parent: WidgetValue<'a>,
index: WidgetValue<'a>,
draggable_id: WidgetValue<'a>,
}

impl<'a> DraggableInfo<'a>{
pub fn new(parent: &'static str, index: u32, draggable_id: &'static str)->Self{
DraggableInfo{
parent: WidgetValue::CString(Cow::Borrowed(parent)),
index: WidgetValue::Unsized32(index),
draggable_id: WidgetValue::CString(Cow::Borrowed(draggable_id)),
}
}
}

#[derive(Clone, Serialize, Deserialize, Debug)]
pub enum WidgetValue<'a>{
Integer32(i32),
Unsized32(u32),
CString(Cow<'a, str>)
}

fn main(){
let mut event_emitter = EventEmitter::new();
event_emitter.on("Print Draggable Value", |dragValue: DraggableInfo| {dbg!(dragValue);});
event_emitter.emit("Print Draggable Value", DraggableInfo::new("root", 0, "layer 1"));
}

但这会导致错误消息:

error: implementation of `Deserialize` is not general enough
--> src\main.rs:34:19
|
34 | event_emitter.on("Print Draggable Value", |dragValue: DraggableInfo| {dbg!(dragValue);});
| ^^ implementation of `Deserialize` is not general enough
|
= note: `DraggableInfo<'_>` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: ...but `DraggableInfo<'_>` actually implements `Deserialize<'1>`, for some specific lifetime `'1`

我不确定 Deserialize<'0> 是什么和 Deserialize<'1>消息所指的生命周期是,或者当编译器说 impl “过于笼统”时的确切含义。我该如何解决这个错误?

最佳答案

问题在评论中被驳回,但您的具体问题在此行中很突出:

#[serde(bound(deserialize = "'de: 'static"))]

作为Serde guide预先警告:

Note that <T> where T: Deserialize<'static> is never what you want. Also Deserialize<'de> + 'static is never what you want. Generally writing 'static anywhere near Deserialize is a sign of being on the wrong track. Use one of the above bounds instead.

这应该具有实际意义:您永远不想从 100% 静态数据反序列化。那些WidgetValue如果你有,它们会在运行时动态地进出范围(被创建/销毁),对吧?..

但是当你定义 CString带有 reference 的变体到原始输入缓冲区(反序列化发生的事件负载)——你必须确保没有一个 WidgetValue永远超过它的输入缓冲区。这就是 Rust 生命周期的目的,它们对机器检查保证 Bad Things™ 不会发生进行编码。

再次来自评论:简单的解决方案是拥有数据而不是借用(引用)它,即

pub enum WidgetValue {
Integer32(i32),
Unsized32(u32),
CString(String),
}

...但是这种简单性会让您付出性能代价,无论何时WidgetValue,堆分配和无偿字符串复制。 s 被传递。你会失去 zero-copy capacity由 Serde 支持。并不是说它本质上是不好的;也许这个价格适合您的应用。

但是,许多程序员选择 Rust 用于那些性能很重要的应用程序。在安全方面也毫不妥协。也就是说:让我们亲自动手吧。


备注:Unsized32是矛盾的,你可能打算写Unsigned32 .

注:在DraggableInfo::new签名,为什么要求借来的字符串切片有'static生命周期?这太严格了。简单 'a就足够了。

the error is clear that the type needs to implement Deserialize for any lifetime

的确; .on signature没有 'de作为通用参数:

pub fn on<F, T>(&mut self, event: &str, callback: F) -> String where
T: Deserialize<'de>,
F: Fn(T) + 'static + Sync + Send,

这意味着调用者无法选择生命周期。这可能是无意的,也许可以尝试询问作者或 event_emitter_rs图书馆;可能是一个微妙的错误,可能是设计使然。

顺便说一句:如果你想使用像 serde_json::from_reader 这样的东西为了在流中真正动态地反序列化——这整个零拷贝的努力是行不通的。这表示在DeserializeOwned约束。 the guide 中也提到了这一事实, For example when deserializing from an IO stream no data can be borrowed.

在这一点上,我放弃了进一步的研究,因为我是在从流中解析 JSON 的上下文中访问这个问题的。这意味着我别无选择,只能做 DeserializeOwned (即在我的数据结构中使用拥有的 String 而不是 &'a str )。这也是有道理的,因为流数据是短暂的,所以从中借用根本行不通。

关于rust - Serde::Deserialize 的实现不够通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68156340/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com