私は、バイトが最終的にパイプに送られ、再構築され、メソッドが呼び出される構造体のシリアライゼーションを行おうとしています。
これらの構造体が適切に実装する特性を作成し、シリアライゼーションに 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();
}
トレイトをタイプとして使用してバイトを再構築しようとすると (送信されている基になるオブジェクトがわからない場合)、コンパイラはトレイトがトレイトを実装していないと文句を言いSized
ます。
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[..]);
このシリアル化 + ポリモーフィズム動作を達成するためのより良いパターンはありますか?