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
//! Traits and corresponding derive macros for enum-based encapsulation.

/// Macros.
#[cfg(feature = "macros")]
pub use enumcapsulate_macros as macros;

/// Derive macros.
#[cfg(feature = "derive")]
pub mod derive {
    pub use super::macros::{
        AsVariant, AsVariantMut, AsVariantRef, Encapsulate, From, FromVariant, IntoVariant,
        IsVariant, TryInto, VariantDiscriminant,
    };
}

/// Used to do variant-to-enum conversions
/// between an outer enum's and its inner variant's type.
pub trait FromVariant<T> {
    /// Converts to this type from the variant's type.
    fn from_variant(variant: T) -> Self;
}

/// Used to do a cheap reference-to-reference reference conversion
/// between an outer enum's and its inner variant's type.
pub trait AsVariantRef<T> {
    /// Returns some reference to the inner value if it is of type `T`, or `None`` if it isn’t.
    fn as_variant_ref(&self) -> Option<&T>;

    /// Returns a copy of the inner value if it is of type `T`, or `None`` if it isn’t.
    fn as_variant(&self) -> Option<T>
    where
        T: Clone,
    {
        self.as_variant_ref().cloned()
    }
}

/// Used to do a cheap mutable-to-mutable reference conversion
/// between an outer enum's and its inner variant's type.
pub trait AsVariantMut<T> {
    /// Returns some mutable reference to the inner value if it is of type `T`, or `None` if it isn’t.
    fn as_variant_mut(&mut self) -> Option<&mut T>;
}

/// Used to do enum-to-variant conversions
/// between an outer enum's and its inner variant's type.
pub trait IntoVariant<T>: Sized {
    /// Converts this type into the variant's type.
    fn into_variant(self) -> Result<T, Self>;
}

/// Convenience umbrella trait used to do a cheap
///
/// - reference-to-reference
/// - mutable-to-mutable reference
/// - reference-to-value
/// - value-to-value
///
/// conversion between an outer enum's and its inner variant's type.
pub trait VariantDowncast {
    /// Returns some reference to the inner value if it is of type `T`, or `None`` if it isn’t.
    fn as_variant_downcast_ref<T>(&self) -> Option<&T>
    where
        Self: AsVariantRef<T>,
    {
        self.as_variant_ref()
    }

    /// Returns some mutable reference to the inner value if it is of type `T`, or `None` if it isn’t.
    fn as_variant_downcast_mut<T>(&mut self) -> Option<&mut T>
    where
        Self: AsVariantMut<T>,
    {
        self.as_variant_mut()
    }

    /// Returns a copy of the inner value if it is of type `T`, or `None`` if it isn’t.
    fn as_variant_downcast<T>(&self) -> Option<T>
    where
        T: Clone,
        Self: AsVariantRef<T>,
    {
        self.as_variant()
    }

    /// Converts this type into the variant's type.
    fn into_variant_downcast<T>(self) -> Result<T, Self>
    where
        Self: IntoVariant<T>,
    {
        self.into_variant()
    }
}

/// Used to check type of an enum's inner variant's type.
pub trait IsVariant {
    /// Returns `true` if `T` matches the variant's type, otherwise `false`.
    fn is_variant<T>(&self) -> bool
    where
        T: 'static + ?Sized;
}

/// Used to obtain an enum variant's discriminant.
pub trait VariantDiscriminant {
    type Discriminant: Eq;

    /// Returns the variant's discriminant.
    fn variant_discriminant(&self) -> Self::Discriminant;
}