2017-02-22 43 views
8

Я пытаюсь выполнить сериализацию структуры, в которой байты в конечном итоге будут отправляться по каналу, реконструированы и методы будут вызваны на них.Как десериализовать в черту, а не конкретный тип?

Я создал черту эти Структуры будут реализовывать по мере необходимости, и я использую 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[..]); 

Есть ли лучший шаблон для достижения этой сериализации + полиморфизм поведения?

+2

Я ... не думаю, что вы можете сделать это. Вы не можете восстановить структуру, если не знаете ее конкретного типа, и вы не можете вызывать методы на ней, если у вас нет указателя на ее таблицу vtable, которую вы не можете найти, если у вас нет доступа к ее конкретному типу. Можете ли вы сериализовать vtable? – trentcl

+0

Кажется, это так, но я надеялся, что кто-то укажет на то, что мне не хватает. У меня есть неидиоматическое решение для этого, но добавляет связь с кодом ... поэтому я ищу что-то лучшее. – Dash83

+3

Вы уверены, что хотите полиморфизм, а не просто перечисление? Вам нужен ваш код для работы с пользовательскими типами? –

ответ

6

Похоже, вы попали в ту же ловушку, в которую я попал, когда я перешел с C++ на Rust. Пытается использовать полиморфизм для моделирования фиксированного набора вариантов типа. Перечисления Руста (подобно перечням Haskell и эквивалентным типам записей Ады) отличаются от классических перечислений на других языках, потому что варианты перечисления могут иметь собственные поля.

Я предлагаю вам изменить свой код

#[derive(Debug, Serialize, Deserialize)] 
enum Contract { 
    Bar { data: Vec<Foo> }, 
    Baz { data: Vec<Foo>, tag: String }, 
} 

#[derive(Debug, Serialize, Deserialize)] 
struct Foo { 
    x: u32, 
    y: u32, 
} 

impl Contract { 
    fn do_something(&self) { 
     match *self { 
      Contract::Bar { ref data } => println!("I'm a Bar and this is my data {:?}", data), 
      Contract::Baz { ref data, ref tag } => { 
       println!("I'm Baz {} and this is my data {:?}", tag, data) 
      } 
     } 
    } 
} 
+0

Использовал структуры Bar и Baz как связанные данные для перечисления, но в значительной степени пошел с этим дизайном. Благодаря! – Dash83

+0

Как насчет наличия произвольного набора типов из признака с параметрами типа? – Shisoft

+0

@Shisoft не уверен, что я понимаю. Почему бы вам не открыть новый вопрос? –

 Смежные вопросы

  • Нет связанных вопросов^_^