I'm porting an image editor from ECMAScript at the moment, and started out by throwing together a de/serializer for the existing (mostly JSON) file format with serde. That came together reasonably smoothly, but left me with a Vec of enums, with different variants for the different layer types (pixmap, layer effects, etc).
But, you can't impl methods on variants, or (to my knowledge) access the fields without matching, and I've got over half a dozen fields per variant. So at this point I'm considering translating to a vector of trait objects after I load the vector of enums using something like the code below, but that would then require defining every variant twice and keeping them in sync.
Is there a Better Way? Or at the very least are there ways of making this approach a bit more readable/maintainable?
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
trait Sing {
fn sing(&self) -> ();
fn curse(&self) -> Womble;
}
struct B32 {
y: i32,
}
struct B16 {
z: i16,
}
impl Sing for B32 {
fn sing(&self) -> () {
println!("Lala from B32{{ y:{} }}", self.y);
}
fn curse(&self) -> Womble {
Womble::B32 { y: self.y }
}
}
impl Sing for B16 {
fn sing(&self) -> () {
println!("Lala from B16{{ z:{} }}", self.z);
}
fn curse(&self) -> Womble {
Womble::B16 { z: self.z }
}
}
#[derive(Serialize, Deserialize)]
#[serde(tag = "wombletype")]
enum Womble {
B32 { y: i32 },
B16 { z: i16 },
}
impl Womble {
fn bless(&self) -> Box<Sing> {
match *self {
Womble::B32 {y} => Box::new(B32{y:y}),
Womble::B16 {z} => Box::new(B16{z:z}),
}
}
}
type BoxList = Vec<Box<Sing>>;
type EnumList = Vec<Womble>;
fn main() {
let list:BoxList = vec![ Box::new(B16{z:160}), Box::new(B32{y:320}),];
for j in &list {
j.sing();
}
let partial_ser: EnumList = list.iter().map(|x| x.curse()).collect();
let serialized = serde_json::to_string_pretty(&partial_ser).unwrap();
println!("\nserialized = {}\n", serialized);
let partial_deser:EnumList = serde_json::from_str(&serialized[..]).unwrap();
let deser:BoxList = partial_deser.iter().map(|x| x.bless()).collect();
for j in deser {
j.sing();
}
}