dtolnay / typetag

Serde serializable and deserializable trait objects
Apache License 2.0
1.19k stars 38 forks source link

Could this work also for Arc<dyn Trait>? #37

Closed gabrik closed 3 years ago

gabrik commented 3 years ago

First, thank you for these very useful macros.

I was wondering if this could work also for Arc<dyn Trait>

I have this basic example code:

use std::fmt::Debug;
use std::collections::HashMap;
use std::sync::Arc;
use std::any::Any;

use serde::{Serialize, Deserialize};

#[typetag::serde(tag = "type")]
trait Data: 'static + Send + Sync + Debug{
    fn as_any(&self) -> &dyn Any;
}

macro_rules! downcast {
    ($ident : ident, $val : expr) => {
            $val.as_any().downcast_ref::<$ident>()
    }
}

#[typetag::serde]
impl Data for String {
    fn as_any(&self) -> &dyn Any {
        self
    }

}

#[derive(Debug, Serialize, Deserialize)]
struct MyDuckingStruct {
    pub x : u8,
    pub y : String,
}

#[typetag::serde]
impl Data for MyDuckingStruct {
    fn as_any(&self) -> &dyn Any {
        self
    }

}

fn main() {
    let mut my_map : HashMap<u8,Arc<dyn Data>> = HashMap::new();

    let s = "this is a ducking string".to_string();

    let mds = MyDuckingStruct {x: 123u8, y: "this is a ducking string in a ducking struct".to_string()};

    my_map.insert(0, Arc::new(s));
    my_map.insert(1, Arc::new(mds));

    println!("Map: {:?}", my_map);

    let any = my_map.get(&1).unwrap().as_any();

    let nds = any.downcast_ref::<MyDuckingStruct>();

    println!("Struct: {:?}", nds);

    let x = my_map.get(&1).unwrap().clone();
    let ds2 = downcast!(MyDuckingStruct, x);

    println!("Struct2: {:?}", ds2);

    let d = my_map.get(&1).unwrap().clone();

    let json = serde_json::to_string(&d).unwrap();

    println!("Serialized {:?}", json)

}

That of course does not compile because of:

error[E0277]: the trait bound `Arc<dyn Data>: _::_serde::Serialize` is not satisfied
    --> src/main.rs:120:38
     |
120  |     let json = serde_json::to_string(&d).unwrap();

Any suggestion? It could be feasible?

khoover commented 3 years ago

You've enabled the rc feature for serde already, right? Serde gates Rc/Arc serialization behind that feature, due to how it doesn't attempt to re-link Rcs that were pointing to the same data after reconstructing them.

gabrik commented 3 years ago

Thanks @khoover I've enabled the rc feature and forgot to close this issue.