#[macro_export]
macro_rules! alias_either {
($type_name:ident, $left_variant:ident, $right_variant:ident) => {
$crate::alias_either!($type_name, $left_variant, $right_variant, [Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash]);
};
($type_name:ident, $left_variant:ident, $right_variant:ident, traits: [$($trait:path),*]) => {
$crate::alias_either!($type_name, $left_variant, $right_variant, [$($trait),*]);
};
($type_name:ident, $left_variant:ident, $right_variant:ident, [$($trait:path),*]) => {
paste::paste! {
#[derive($($trait),*)]
pub enum $type_name<L, R> {
$left_variant(L),
$right_variant(R),
}
impl<L, R> $type_name<L, R> {
pub fn [<is_ $left_variant:lower>](&self) -> bool {
matches!(self, $type_name::$left_variant(_))
}
pub fn [<is_ $right_variant:lower>](&self) -> bool {
matches!(self, $type_name::$right_variant(_))
}
pub fn [<as_ $left_variant:lower>](&self) -> Option<&L> {
match self {
$type_name::$left_variant(v) => Some(v),
_ => None,
}
}
pub fn [<as_ $left_variant:lower _mut>](&mut self) -> Option<&mut L> {
match self {
$type_name::$left_variant(v) => Some(v),
_ => None,
}
}
pub fn [<as_ $right_variant:lower>](&self) -> Option<&R> {
match self {
$type_name::$right_variant(v) => Some(v),
_ => None,
}
}
pub fn [<as_ $right_variant:lower _mut>](&mut self) -> Option<&mut R> {
match self {
$type_name::$right_variant(v) => Some(v),
_ => None,
}
}
pub fn [<map_ $left_variant:lower>]<T, F: FnOnce(L) -> T>(self, f: F) -> $type_name<T, R> {
match self {
$type_name::$left_variant(v) => $type_name::$left_variant(f(v)),
$type_name::$right_variant(v) => $type_name::$right_variant(v),
}
}
pub fn [<map_ $right_variant:lower>]<T, F: FnOnce(R) -> T>(self, f: F) -> $type_name<L, T> {
match self {
$type_name::$left_variant(v) => $type_name::$left_variant(v),
$type_name::$right_variant(v) => $type_name::$right_variant(f(v)),
}
}
pub fn [<unwrap_ $left_variant:lower>](self) -> L {
match self {
$type_name::$left_variant(v) => v,
$type_name::$right_variant(_) => {
panic!("called `unwrap_{}()` on a `{}`", stringify!([<$left_variant:lower>]), stringify!($right_variant))
}
}
}
pub fn [<unwrap_ $right_variant:lower>](self) -> R {
match self {
$type_name::$right_variant(v) => v,
$type_name::$left_variant(_) => {
panic!("called `unwrap_{}()` on a `{}`", stringify!([<$right_variant:lower>]), stringify!($left_variant))
}
}
}
}
}
};
}