Skip to main content

cba/baccarat/
types.rs

1/// Macro to define a `When` enum with exactly three variants:
2/// Never, Auto, Always. Preserves enum and variant metadata.
3///
4/// # Example
5/// ```
6/// use cba::define_when;
7///
8/// define_when! {
9///    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10///    #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
11///    pub enum When {
12///        #[cfg_attr(feature = "serde", serde(alias = "false", alias = "never"))]
13///        Never,
14///        #[default]
15///        #[cfg_attr(feature = "serde", serde(alias = "auto"))]
16///        Auto,
17///        #[cfg_attr(feature = "serde", serde(alias = "true", alias = "always"))]
18///        Always
19///   }
20/// }
21/// ```
22#[macro_export]
23macro_rules! define_when {
24        (
25            $(#[$enum_meta:meta])*
26            $vis:vis enum $name:ident {
27                $(#[$never_meta:meta])* $never:ident,
28                $(#[$auto_meta:meta])* $auto:ident,
29                $(#[$always_meta:meta])* $always:ident$(,)?
30            }
31        ) => {
32            $(#[$enum_meta])*
33            $vis enum $name {
34                $(#[$never_meta])* $never,
35                $(#[$auto_meta])* $auto,
36                $(#[$always_meta])* $always,
37            }
38
39            impl From<$name> for Option<bool> {
40                fn from(w: $name) -> Self {
41                    match w {
42                        $name::$never => Some(false),
43                        $name::$always => Some(true),
44                        $name::$auto => None,
45                    }
46                }
47            }
48
49            impl From<Option<bool>> for $name {
50                fn from(opt: Option<bool>) -> Self {
51                    match opt {
52                        Some(true) => $name::$always,
53                        Some(false) => $name::$never,
54                        None => $name::$auto,
55                    }
56                }
57            }
58
59            impl From<bool> for $name {
60                fn from(b: bool) -> Self {
61                    if b { $name::$always } else { $name::$never }
62                }
63            }
64
65            impl $name {
66                pub fn unwrap_or(self, default: bool) -> bool {
67                    match self {
68                        $name::$never => false,
69                        $name::$always => true,
70                        $name::$auto => default,
71                    }
72                }
73
74                pub fn unwrap_or_else<F>(self, f: F) -> bool
75                where F: FnOnce() -> bool
76                {
77                    match self {
78                        $name::$never => false,
79                        $name::$always => true,
80                        $name::$auto => f(),
81                    }
82                }
83
84                pub fn is_default(&self) -> bool { matches!(self, $name::$auto) }
85                pub fn is_always(&self) -> bool { matches!(self, $name::$always) }
86                pub fn is_never(&self) -> bool { matches!(self, $name::$never) }
87                pub fn is_none(&self) -> bool { matches!(self, $name::$auto) }
88            }
89        }
90    }
91
92/// Macro to define an `Either` enum with exactly two variants: Left, Right.
93///```rust
94/// use cba::define_either;
95///
96/// define_either! {
97///     #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
98///     #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
99///     pub enum Either<L, R = L> {
100///         Left,
101///         Right
102///     }
103/// }
104/// ```
105#[macro_export]
106macro_rules! define_either {
107        (
108            $(#[$enum_meta:meta])*
109            $vis:vis enum $name:ident<$l:ident, $r:ident = $default_r:ident> {
110                $(#[$left_meta:meta])* $left:ident,
111                $(#[$right_meta:meta])* $right:ident$(,)?
112            }
113        ) => {
114            $(#[$enum_meta])*
115            $vis enum $name<$l, $r = $default_r> {
116                $(#[$left_meta])* $left($l),
117                $(#[$right_meta])* $right($r),
118            }
119
120            impl<$l, $r> $name<$l, $r> {
121                pub fn right(self) -> Option<$r> {
122                    match self {
123                        $name::$right(r) => Some(r),
124                        $name::$left(_) => None,
125                    }
126                }
127
128                pub fn left(self) -> Option<$l> {
129                    match self {
130                        $name::$left(l) => Some(l),
131                        $name::$right(_) => None,
132                    }
133                }
134
135                pub fn _left(self) -> $l { self.left().unwrap() }
136                pub fn _right(self) -> $r { self.right().unwrap() }
137
138                pub fn as_ref(&self) -> $name<&$l, &$r> {
139                    match self {
140                        $name::$left(l) => $name::$left(l),
141                        $name::$right(r) => $name::$right(r),
142                    }
143                }
144
145                pub fn as_mut(&mut self) -> $name<&mut $l, &mut $r> {
146                    match self {
147                        $name::$left(l) => $name::$left(l),
148                        $name::$right(r) => $name::$right(r),
149                    }
150                }
151
152                pub fn map_left<F, LL>(self, f: F) -> $name<LL, $r>
153                where F: FnOnce($l) -> LL
154                {
155                    match self {
156                        $name::$left(l) => $name::$left(f(l)),
157                        $name::$right(r) => $name::$right(r),
158                    }
159                }
160
161                pub fn map_right<F, RR>(self, f: F) -> $name<$l, RR>
162                where F: FnOnce($r) -> RR
163                {
164                    match self {
165                        $name::$left(l) => $name::$left(l),
166                        $name::$right(r) => $name::$right(f(r)),
167                    }
168                }
169
170                pub fn _map_right<F>(self, f: F) -> $l
171                where F: FnOnce($r) -> $l
172                {
173                    match self {
174                        $name::$left(l) => l,
175                        $name::$right(r) => f(r),
176                    }
177                }
178
179                pub fn is_left(&self) -> bool { matches!(self, $name::$left(_)) }
180
181                pub fn swap(self) -> $name<$r, $l> {
182                    match self {
183                        $name::$left(x) => $name::$right(x),
184                        $name::$right(x) => $name::$left(x),
185                    }
186                }
187
188                pub fn into_result(self) -> Result<$l, $r> {
189                    match self {
190                        $name::$left(l) => Ok(l),
191                        $name::$right(r) => Err(r),
192                    }
193                }
194            }
195        }
196    }