use std::mem::take;
use crate::{DBData, declare_trait_object, dynamic::erase::Erase};
use super::{Data, DataTrait};
pub trait Opt<T: DataTrait + ?Sized>: Data {
fn get(&self) -> Option<&T>;
fn get_mut(&mut self) -> Option<&mut T>;
fn set_none(&mut self);
#[allow(clippy::wrong_self_convention)]
fn from_ref(&mut self, v: &T);
#[allow(clippy::wrong_self_convention)]
fn from_val(&mut self, v: &mut T);
fn set_some_with(&mut self, f: &mut dyn FnMut(&mut T));
}
impl<T, Trait> Opt<Trait> for Option<T>
where
Trait: DataTrait + ?Sized,
T: DBData + Erase<Trait>,
{
fn get(&self) -> Option<&Trait> {
self.as_ref().map(Erase::erase)
}
fn get_mut(&mut self) -> Option<&mut Trait> {
self.as_mut().map(Erase::erase_mut)
}
fn set_none(&mut self) {
*self = None;
}
fn from_ref(&mut self, v: &Trait) {
*self = Some(unsafe { v.downcast::<T>().clone() })
}
fn from_val(&mut self, v: &mut Trait) {
*self = Some(unsafe { take(v.downcast_mut::<T>()) })
}
fn set_some_with(&mut self, f: &mut dyn FnMut(&mut Trait)) {
let mut v: T = Default::default();
f(v.erase_mut());
*self = Some(v);
}
}
declare_trait_object!(DynOpt<T> = dyn Opt<T>
where
T: DataTrait + ?Sized
);