Skip to main content

structural/enums/
enum_ext.rs

1use crate::{
2    enums::{IsVariant, VariantProxy},
3    path::TStr,
4};
5
6/// Extension trait for enums.
7///
8/// This trait has these methods:
9///
10/// - `*_variant`: For fallibly converting an enum to a VariantProxy of a passed variant.
11/// As opposed to calling StructuralExt methods with a `fp!(::Foo)` argument,
12/// this allows recovering the enum when it's not the passed variant.
13///
14pub trait EnumExt {
15    /// Fallibly converts a reference to an enum into
16    /// a reference of a VariantProxy of some variant.
17    ///
18    /// # Example
19    ///
20    /// ```
21    /// use structural::{ts,TS,StructuralExt};
22    /// use structural::for_examples::Variants;
23    /// use structural::enums::{EnumExt,VariantProxy};
24    ///
25    /// let this=Variants::Foo(11,22);
26    /// {
27    ///     let proxy: &VariantProxy<Variants,TS!(Foo)>=
28    ///         this.as_variant(ts!(Foo)).unwrap();
29    ///
30    ///     assert_eq!( proxy.field_(ts!(0)), &11);
31    ///     assert_eq!( proxy.field_(ts!(1)), &22);
32    /// }
33    /// {
34    ///     assert_eq!( this.as_variant(ts!(Bar)), Err(&this) );
35    /// }
36    /// ```
37    #[inline(always)]
38    fn as_variant<V>(&self, vari: TStr<V>) -> Result<&VariantProxy<Self, TStr<V>>, &Self>
39    where
40        Self: IsVariant<TStr<V>>,
41    {
42        if IsVariant::is_variant_(self, vari) {
43            unsafe { Ok(VariantProxy::from_ref(self, vari)) }
44        } else {
45            Err(self)
46        }
47    }
48
49    /// Fallibly converts a mutable reference to an enum into
50    /// a mutable reference of a VariantProxy of some variant.
51    ///
52    /// # Example
53    ///
54    /// ```
55    /// use structural::{ts,TS,StructuralExt};
56    /// use structural::for_examples::Variants;
57    /// use structural::enums::{EnumExt,VariantProxy};
58    ///
59    /// let mut this=Variants::Bar("hello");
60    /// let mut other=this.clone();
61    ///
62    /// {
63    ///     let proxy: &mut VariantProxy<Variants,TS!(Bar)>=
64    ///         this.as_mut_variant(ts!(Bar)).unwrap();
65    ///    
66    ///     assert_eq!( proxy.field_(ts!(0)), &"hello");
67    ///     assert_eq!( proxy.field_mut(ts!(0)), &mut"hello");
68    /// }
69    /// {
70    ///     assert_eq!( this.as_mut_variant(ts!(Foo)), Err(&mut other) );
71    ///     assert_eq!( this.as_mut_variant(ts!(Baz)), Err(&mut other) );
72    ///     assert_eq!( this.as_mut_variant(ts!(Boom)), Err(&mut other) );
73    /// }
74    /// ```
75    #[inline(always)]
76    fn as_mut_variant<V>(
77        &mut self,
78        vari: TStr<V>,
79    ) -> Result<&mut VariantProxy<Self, TStr<V>>, &mut Self>
80    where
81        Self: IsVariant<TStr<V>>,
82    {
83        if IsVariant::is_variant_(&*self, vari) {
84            unsafe { Ok(VariantProxy::from_mut(self, vari)) }
85        } else {
86            Err(self)
87        }
88    }
89
90    /// Fallibly converts a raw pointer to an enum into
91    /// a raw pointer of a VariantProxy of some variant.
92    ///
93    /// # Example
94    ///
95    /// ```
96    /// use structural::{ts,TS,StructuralExt};
97    /// use structural::for_examples::Variants;
98    /// use structural::enums::{EnumExt,VariantProxy};
99    ///
100    /// let mut this=Variants::Baz(None);
101    ///
102    /// unsafe{
103    ///     let proxy: *mut VariantProxy<Variants,TS!(Baz)>=
104    ///         Variants::as_raw_mut_variant(&mut this,ts!(Baz)).unwrap();
105    ///    
106    ///     assert_eq!( (*proxy).field_(ts!(0)), &None);;
107    ///     assert_eq!( (*proxy).field_mut(ts!(0)), &None);;
108    /// }
109    /// unsafe{
110    ///     assert_eq!(
111    ///         Variants::as_raw_mut_variant(&mut this,ts!(Foo)),
112    ///         Err(&mut this as *mut Variants)
113    ///     );
114    ///     assert_eq!(
115    ///         Variants::as_raw_mut_variant(&mut this,ts!(Bar)),
116    ///         Err(&mut this as *mut Variants)
117    ///     );
118    ///     assert_eq!(
119    ///         Variants::as_raw_mut_variant(&mut this,ts!(Boom)),
120    ///         Err(&mut this as *mut Variants)
121    ///     );
122    /// }
123    ///
124    /// ```
125    ///
126    /// # Safety
127    ///
128    /// You must pass a pointer to a fully initialized instance of `Self`.
129    #[inline(always)]
130    unsafe fn as_raw_mut_variant<V>(
131        this: *mut Self,
132        vari: TStr<V>,
133    ) -> Result<*mut VariantProxy<Self, TStr<V>>, *mut Self>
134    where
135        Self: IsVariant<TStr<V>>,
136    {
137        if IsVariant::is_variant_(&*this, vari) {
138            Ok(VariantProxy::from_raw_mut(this, vari))
139        } else {
140            Err(this)
141        }
142    }
143
144    /// Fallibly converts an enum into a VariantProxy of some variant.
145    ///
146    /// # Example
147    ///
148    /// ```
149    /// use structural::{ts,TS,StructuralExt};
150    /// use structural::for_examples::Variants;
151    /// use structural::enums::{EnumExt,VariantProxy};
152    ///
153    /// use std::cmp::Ordering;
154    ///
155    /// let this=Variants::Baz(Some(Ordering::Less));
156    ///
157    /// {
158    ///     let mut proxy: VariantProxy<Variants,TS!(Baz)>=
159    ///         this.into_variant(ts!(Baz)).unwrap();
160    ///    
161    ///     assert_eq!( proxy.field_(ts!(0)), &Some(Ordering::Less));
162    ///     assert_eq!( proxy.field_mut(ts!(0)), &mut Some(Ordering::Less));
163    ///     assert_eq!( proxy.into_field(ts!(0)), Some(Ordering::Less));
164    /// }
165    /// {
166    ///     assert_eq!(this.into_variant(ts!(Foo)), Err(this));
167    ///     assert_eq!(this.into_variant(ts!(Bar)), Err(this));
168    ///     assert_eq!(this.into_variant(ts!(Boom)), Err(this));
169    /// }
170    ///
171    /// ```
172    #[inline(always)]
173    fn into_variant<V>(self, vari: TStr<V>) -> Result<VariantProxy<Self, TStr<V>>, Self>
174    where
175        Self: IsVariant<TStr<V>> + Sized,
176    {
177        if IsVariant::is_variant_(&self, vari) {
178            unsafe { Ok(VariantProxy::new(self, vari)) }
179        } else {
180            Err(self)
181        }
182    }
183}
184
185impl<This: ?Sized> EnumExt for This {}