如果有的话,如何在 Rust 中添加多态特征对象的反序列化? [英] How can deserialization of polymorphic trait objects be added in Rust if at all?

查看:20
本文介绍了如果有的话,如何在 Rust 中添加多态特征对象的反序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决序列化和反序列化Box的问题.我知道在封闭类型层次结构的情况下,推荐的方法是使用枚举并且它们的序列化没有问题,但在我的情况下使用枚举是一个不合适的解决方案.

I'm trying to solve the problem of serializing and deserializing Box<SomeTrait>. I know that in the case of a closed type hierarchy, the recommended way is to use an enum and there are no issues with their serialization, but in my case using enums is an inappropriate solution.

起初我尝试使用 Serde,因为它是事实上的 Rust 序列化机制.Serde 能够序列化 Box 但在 X 是特征的情况下不能.Serialize trait 无法为 trait 实现对象,因为它具有通用方法.这个特殊的问题可以通过使用 erased-serde 来解决,所以 Box 的序列化可以解决这个问题. 可以工作.

At first I tried to use Serde as it is the de-facto Rust serialization mechanism. Serde is capable of serializing Box<X> but not in the case when X is a trait. The Serialize trait can’t be implemented for trait objects because it has generic methods. This particular issue can be solved by using erased-serde so serialization of Box<SomeTrait> can work.

主要问题是反序列化.要反序列化多态类型,您需要在序列化数据中有一些类型标记.这个标记应该先反序列化,然后用来动态获取将返回Box的函数.

The main problem is deserialization. To deserialize polymorphic type you need to have some type marker in serialized data. This marker should be deserialized first and after that used to dynamically get the function that will return Box<SomeTrait>.

std::any::TypeId 可以用作标记类型,但主要问题是如何动态获取反序列化函数.我不考虑为每个应在应用程序初始化期间手动调用的多态类型注册一个函数.

std::any::TypeId could be used as a marker type, but the main problem is how to dynamically get the deserialization function. I do not consider the option of registering a function for each polymorphic type that should be called manually during application initialization.

我知道两种可能的方法:

I know two possible ways to do it:

  1. 像C#这样有运行时反射的语言可以用它来获取反序列化方法.
  2. 在 C++ 中,谷类库使用静态对象的魔法在库初始化时在静态映射中注册反序列化器.

但是这些选项在 Rust 中都不可用.如果有的话,如何在 Rust 中添加多态对象的反序列化?

But neither of these options is available in Rust. How can deserialization of polymorphic objects be added in Rust if at all?

推荐答案

这已经由 dtolnay 实施.

这个概念很聪明,在README中有解释:

The concept is quite clever ans is explained in the README:

它是如何工作的?

我们使用 inventory crate 来生成您的实现的注册表trait,它建立在 ctor crate 上以连接初始化函数插入到注册表中.第一个 Box 反序列化将执行迭代注册表和构建标签映射到反序列化函数的工作.随后的反序列化在该映射中找到正确的反序列化函数.erased-serde crate 也涉及到,要做到这一切一种不会破坏对象安全的方法.

We use the inventory crate to produce a registry of impls of your trait, which is built on the ctor crate to hook up initialization functions that insert into the registry. The first Box<dyn Trait> deserialization will perform the work of iterating the registry and building a map of tags to deserialization functions. Subsequent deserializations find the right deserialization function in that map. The erased-serde crate is also involved, to do this all in a way that does not break object safety.

总而言之,声明为 [de]serializable 的 trait 的每个实现都在编译时注册,并且在 trait 对象的 [de] 序列化的情况下在运行时解决.

To summarize, every implementation of the trait declared as [de]serializable is registered at compile-time, and this is resolved at runtime in case of [de]serialization of a trait object.

这篇关于如果有的话,如何在 Rust 中添加多态特征对象的反序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆