use std::any::Any;
use std::rc::Rc;
use std::cell::RefCell;
use std::sync::Arc;
use std::sync::RwLock;
#[derive(Debug)]
pub enum UserData {
BoxedData ( Box < RefCell < dyn Any > > ),
SharedData ( Rc < RefCell < dyn Any > > ),
SyncData ( Arc < RwLock < dyn Any > > ),
NoData,
}
use UserData::*;
impl UserData {
pub fn boxed<D:'static>(user_data: D) -> Self {
BoxedData(Box::new(RefCell::new(user_data)))
}
pub fn shared<D:'static>(user_data: D) -> Self {
SharedData(Rc::new(RefCell::new(user_data)))
}
pub fn sync<D:'static>(user_data: D) -> Self {
SyncData(Arc::new(RwLock::new(user_data)))
}
pub fn apply<D:'static, F, R>(&self, f: F) -> R
where
F: FnOnce(&D) -> R
{
const ERRMSG: &str = "Unable to downcast to requested type.";
match self {
BoxedData(d) => {
f(d.borrow().downcast_ref::<D>().expect(ERRMSG))
},
SharedData(d) => {
f(d.borrow().downcast_ref::<D>().expect(ERRMSG))
},
SyncData(d) => {
f((*d.read().unwrap()).downcast_ref::<D>().expect(ERRMSG))
},
NoData => { panic!("Can't downcast `NoData`.") },
}
}
pub fn apply_mut<D:'static, F, R>(&self, f: F) -> R
where
F: FnOnce(&mut D) -> R
{
const ERRMSG: &str = "Unable to downcast to requested type.";
match self {
BoxedData(d) => {
f(d.borrow_mut().downcast_mut::<D>().expect(ERRMSG))
},
SharedData(d) => {
f(d.borrow_mut().downcast_mut::<D>().expect(ERRMSG))
},
SyncData(d) => {
f((*d.write().unwrap()).downcast_mut::<D>().expect(ERRMSG))
},
NoData => { panic!("Can't downcast `NoData`.") },
}
}
}
impl Clone for UserData {
fn clone(&self) -> Self {
match self {
SharedData(d) => { SharedData(d.clone()) },
SyncData(d) => { SyncData(d.clone()) },
NoData => { NoData },
BoxedData(_) => {
panic!("Can't clone `BoxedData`. If user data needs to be \
shared, The `SharedData` or `SyncData` variants of \
`UserData` should be used.")
},
}
}
}
impl Default for UserData {
fn default() -> Self { NoData }
}