Skip to main content

dbsp/dynamic/
option.rs

1use std::mem::take;
2
3use crate::{DBData, declare_trait_object, dynamic::erase::Erase};
4
5use super::{Data, DataTrait};
6
7/// An dynamically typed interface to `Option<>`.
8///
9/// The type argument `T` is a trait object type that represents
10/// the inner value of the `Option` type.
11pub trait Opt<T: DataTrait + ?Sized>: Data {
12    /// Return a reference to the inner value or `None` if the value is not set.
13    fn get(&self) -> Option<&T>;
14
15    /// Return a mutable reference to the inner value of `None` if the value is not set.
16    fn get_mut(&mut self) -> Option<&mut T>;
17
18    /// Set the value to `None`.
19    fn set_none(&mut self);
20
21    /// Clone the value of `v` into `self`.
22    #[allow(clippy::wrong_self_convention)]
23    fn from_ref(&mut self, v: &T);
24
25    /// Move the value of `v` into `self` without cloning.  Clears the contents of `v`,
26    /// i.e., sets it to the default value for the type.
27    #[allow(clippy::wrong_self_convention)]
28    fn from_val(&mut self, v: &mut T);
29
30    /// Put a fresh value in `self` and call `f` to initialize it.
31    fn set_some_with(&mut self, f: &mut dyn FnMut(&mut T));
32}
33
34impl<T, Trait> Opt<Trait> for Option<T>
35where
36    Trait: DataTrait + ?Sized,
37    T: DBData + Erase<Trait>,
38{
39    fn get(&self) -> Option<&Trait> {
40        self.as_ref().map(Erase::erase)
41    }
42
43    fn get_mut(&mut self) -> Option<&mut Trait> {
44        self.as_mut().map(Erase::erase_mut)
45    }
46
47    fn set_none(&mut self) {
48        *self = None;
49    }
50
51    fn from_ref(&mut self, v: &Trait) {
52        *self = Some(unsafe { v.downcast::<T>().clone() })
53    }
54
55    fn from_val(&mut self, v: &mut Trait) {
56        *self = Some(unsafe { take(v.downcast_mut::<T>()) })
57    }
58
59    fn set_some_with(&mut self, f: &mut dyn FnMut(&mut Trait)) {
60        let mut v: T = Default::default();
61        f(v.erase_mut());
62        *self = Some(v);
63    }
64}
65
66declare_trait_object!(DynOpt<T> = dyn Opt<T>
67where
68    T: DataTrait + ?Sized
69);