1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

use crate::*;
pub use enso_shapely::CloneRef;



// ================
// === CloneRef ===
// ================

/// Clone for internal-mutable structures. This trait can be implemented only if mutating one
/// structure will be reflected in all of its clones. Please note that it does not mean that all the
/// fields needs to provide internal mutability as well. For example, a structure can remember it's
/// creation time and store it as `f32`. As long as it cannot be mutated, the structure can
/// implement `CloneRef`. In order to guide the auto-deriving mechanism, it is advised to wrap all
/// immutable fields in the `Immutable` newtype.
pub trait CloneRef: Sized {
    fn clone_ref(&self) -> Self;
}


// === Macros ===

#[macro_export]
macro_rules! impl_clone_ref_as_clone {
    ([$($bounds:tt)*] $($toks:tt)*) => {
        impl <$($bounds)*> CloneRef for $($toks)* {
            fn clone_ref(&self) -> Self {
                self.clone()
            }
        }

        impl <$($bounds)*> From<&$($toks)*> for $($toks)* {
            fn from(t:&$($toks)*) -> Self {
                t.clone_ref()
            }
        }
    };

    ($($toks:tt)*) => {
        impl CloneRef for $($toks)* {
            fn clone_ref(&self) -> Self {
                self.clone()
            }
        }

        impl From<&$($toks)*> for $($toks)* {
            fn from(t:&$($toks)*) -> Self {
                t.clone_ref()
            }
        }
    };
}

#[macro_export]
macro_rules! impl_clone_ref_as_clone_no_from {
    ([$($bounds:tt)*] $($toks:tt)*) => {
        impl <$($bounds)*> CloneRef for $($toks)* {
            fn clone_ref(&self) -> Self {
                self.clone()
            }
        }
    };

    ($($toks:tt)*) => {
        impl CloneRef for $($toks)* {
            fn clone_ref(&self) -> Self {
                self.clone()
            }
        }
    };
}


// === Prim Impls ===

impl_clone_ref_as_clone_no_from!(());
impl_clone_ref_as_clone_no_from!(f32);
impl_clone_ref_as_clone_no_from!(f64);
impl_clone_ref_as_clone_no_from!(i32);
impl_clone_ref_as_clone_no_from!(i64);
impl_clone_ref_as_clone_no_from!(u32);
impl_clone_ref_as_clone_no_from!(u64);
impl_clone_ref_as_clone_no_from!(usize);
impl_clone_ref_as_clone_no_from!(std::any::TypeId);
impl_clone_ref_as_clone_no_from!([T] PhantomData<T>);
impl_clone_ref_as_clone_no_from!([T:?Sized] Rc<T>);
impl_clone_ref_as_clone_no_from!([T:?Sized] Weak<T>);

impl_clone_ref_as_clone_no_from!(wasm_bindgen::JsValue);
impl_clone_ref_as_clone_no_from!(web_sys::HtmlDivElement);
impl_clone_ref_as_clone_no_from!(web_sys::HtmlElement);
impl_clone_ref_as_clone_no_from!(web_sys::Performance);
impl_clone_ref_as_clone_no_from!(web_sys::WebGl2RenderingContext);
impl_clone_ref_as_clone_no_from!(web_sys::HtmlCanvasElement);
impl_clone_ref_as_clone_no_from!(web_sys::EventTarget);


// === Option ===

/// Trait for types that can be internally cloned using `CloneRef`, like `Option<&T>`.
#[allow(missing_docs)]
pub trait ClonedRef {
    type Output;
    fn cloned_ref(&self) -> Self::Output;
}

impl<T:CloneRef> ClonedRef for Option<&T> {
    type Output = Option<T>;
    fn cloned_ref(&self) -> Self::Output {
        self.map(|t| t.clone_ref())
    }
}

impl<T:CloneRef> ClonedRef for Option<&mut T> {
    type Output = Option<T>;
    fn cloned_ref(&self) -> Self::Output {
        self.as_ref().map(|t| t.clone_ref())
    }
}