macro_rules! define_variant {
(
$name:ident < $t0:ident $(, $t:ident)* >
= $v0:ident($g0:ident, $g0m:ident)
$(, $idx:literal : $v:ident < $ty:ident > ($g:ident, $gm:ident) )*
) => {
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum $name<$t0 $(, $t)*> {
$v0($t0),
$( $v($ty), )*
}
impl<$t0 $(, $t)*> $name<$t0 $(, $t)*> {
pub fn index(&self) -> usize {
match self {
Self::$v0(_) => 0,
$( Self::$v(_) => $idx, )*
}
}
pub fn valueless_by_exception(&self) -> bool {
false
}
pub fn $g0(&self) -> ::core::option::Option<&$t0> {
match self {
Self::$v0(x) => ::core::option::Option::Some(x),
#[allow(unreachable_patterns)]
_ => ::core::option::Option::None,
}
}
pub fn $g0m(&mut self) -> ::core::option::Option<&mut $t0> {
match self {
Self::$v0(x) => ::core::option::Option::Some(x),
#[allow(unreachable_patterns)]
_ => ::core::option::Option::None,
}
}
$(
pub fn $g(&self) -> ::core::option::Option<&$ty> {
match self {
Self::$v(x) => ::core::option::Option::Some(x),
#[allow(unreachable_patterns)]
_ => ::core::option::Option::None,
}
}
pub fn $gm(&mut self) -> ::core::option::Option<&mut $ty> {
match self {
Self::$v(x) => ::core::option::Option::Some(x),
#[allow(unreachable_patterns)]
_ => ::core::option::Option::None,
}
}
)*
}
impl<$t0: ::core::default::Default $(, $t)*> ::core::default::Default for $name<$t0 $(, $t)*> {
fn default() -> Self {
Self::$v0(<$t0 as ::core::default::Default>::default())
}
}
};
}
define_variant!(Variant1<T0> = V0(get_if_0, get_if_0_mut));
define_variant!(
Variant2<T0, T1> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut)
);
define_variant!(
Variant3<T0, T1, T2> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut),
2: V2<T2>(get_if_2, get_if_2_mut)
);
define_variant!(
Variant4<T0, T1, T2, T3> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut),
2: V2<T2>(get_if_2, get_if_2_mut),
3: V3<T3>(get_if_3, get_if_3_mut)
);
define_variant!(
Variant5<T0, T1, T2, T3, T4> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut),
2: V2<T2>(get_if_2, get_if_2_mut),
3: V3<T3>(get_if_3, get_if_3_mut),
4: V4<T4>(get_if_4, get_if_4_mut)
);
define_variant!(
Variant6<T0, T1, T2, T3, T4, T5> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut),
2: V2<T2>(get_if_2, get_if_2_mut),
3: V3<T3>(get_if_3, get_if_3_mut),
4: V4<T4>(get_if_4, get_if_4_mut),
5: V5<T5>(get_if_5, get_if_5_mut)
);
define_variant!(
Variant7<T0, T1, T2, T3, T4, T5, T6> = V0(get_if_0, get_if_0_mut),
1: V1<T1>(get_if_1, get_if_1_mut),
2: V2<T2>(get_if_2, get_if_2_mut),
3: V3<T3>(get_if_3, get_if_3_mut),
4: V4<T4>(get_if_4, get_if_4_mut),
5: V5<T5>(get_if_5, get_if_5_mut),
6: V6<T6>(get_if_6, get_if_6_mut)
);
#[cfg(test)]
mod tests {
use super::{Variant2, Variant3};
use alloc::string::{String, ToString};
#[test]
fn variant_behavior() {
let v: Variant2<i32, String> = Variant2::default();
assert_eq!(v.get_if_0(), Some(&0));
assert!(v.get_if_1().is_none());
assert_eq!(v.index(), 0);
assert!(!v.valueless_by_exception());
let v1: Variant2<i32, String> = Variant2::V1("hi".to_string());
assert_eq!(v1.get_if_1().map(String::as_str), Some("hi"));
assert_eq!(v1.index(), 1);
let mut m: Variant2<i32, String> = Variant2::V0(5);
m = Variant2::V1("x".to_string());
let mc = m.clone();
assert_eq!(m, mc);
let a: Variant2<i32, String> = Variant2::V0(0);
assert_eq!(a, Variant2::<i32, String>::default());
assert_ne!(v1, Variant2::V1("me".to_string()));
assert_ne!(v1, Variant2::V0(1));
let t: Variant3<i32, bool, String> = Variant3::V2("z".to_string());
let rendered = match &t {
Variant3::V0(n) => n.to_string(),
Variant3::V1(b) => b.to_string(),
Variant3::V2(s) => s.clone(),
};
assert_eq!(rendered, "z");
}
}