【发布时间】:2017-02-22 13:32:41
【问题描述】:
我正在尝试进行结构序列化,其中字节最终将通过管道发送、重构并在其上调用方法。
我创建了一个特征,这些结构将根据需要实现,我正在使用 serde 和 serde-cbor 进行序列化:
extern crate serde_cbor;
#[macro_use]
extern crate serde_derive;
extern crate serde;
use serde_cbor::ser::*;
use serde_cbor::de::*;
trait Contract {
fn do_something(&self);
}
#[derive(Debug, Serialize, Deserialize)]
struct Foo {
x: u32,
y: u32,
}
#[derive(Debug, Serialize, Deserialize)]
struct Bar {
data: Vec<Foo>,
}
#[derive(Debug, Serialize, Deserialize)]
struct Baz {
data: Vec<Foo>,
tag: String,
}
impl Contract for Bar {
fn do_something(&self) {
println!("I'm a Bar and this is my data {:?}", self.data);
}
}
impl Contract for Baz {
fn do_something(&self) {
println!("I'm Baz {} and this is my data {:?}", self.tag, self.data);
}
}
fn main() {
let data = Bar { data: vec![Foo { x: 1, y: 2 }, Foo { x: 3, y: 4 }, Foo { x: 7, y: 8 }] };
data.do_something();
let value = to_vec(&data).unwrap();
let res: Result<Contract, _> = from_reader(&value[..]);
let res = res.unwrap();
println!("{:?}", res);
res.do_something();
}
当我尝试使用 trait 作为类型来重构字节时(假设我不知道正在发送哪个底层对象),编译器会抱怨该 trait 没有实现 Sized trait:
error[E0277]: the trait bound `Contract: std::marker::Sized` is not satisfied --> src/main.rs:52:15 | 52 | let res: Result<Contract, _> = from_reader(&value[..]); | ^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `Contract` | = note: `Contract` does not have a constant size known at compile-time = note: required by `std::result::Result`
我想这是有道理的,因为编译器不知道结构应该有多大,也不知道如何为它排列字节。如果我更改反序列化对象的行以指定实际的结构类型,它会起作用:
let res: Result<Bar, _> = from_reader(&value[..]);
有没有更好的模式来实现这种序列化+多态行为?
【问题讨论】:
-
我……不认为你能做到。除非您知道它的具体类型,否则您无法恢复该结构,并且除非您有指向其 vtable 的指针,否则您无法在其上调用方法——除非您有权访问其具体类型,否则您无法弄清楚。你能序列化一个 vtable 吗?
-
似乎是这样,但我希望有人能指出我遗漏的东西。我对此有一个非惯用的解决方案,但增加了对代码的耦合......所以我正在寻找更好的东西。
-
你确定你想要多态而不是简单的枚举吗?你需要你的代码来处理用户提供的类型吗?
-
我……你知道……但是……不。你是对的,@ker。当使用带有关联数据的枚举时,我所拥有的“非惯用”解决方案变得更加自然。我一直尝试将枚举用作标准 C 枚举,但我可以更改我的设计以使用枚举。如果您将您的建议作为答案发布,我会接受。
-
反序列化成一个还为所有其他
Into实现Contract实现的实现怎么样?
标签: serialization rust serde cbor