use crate::{Pick, Tupl};
pub trait OptionOfTuple<T: Tupl> {
fn on<const N: usize>(self) -> Option<T::At>
where
T: Pick<N>;
}
impl<T: Tupl> OptionOfTuple<T> for Option<T> {
fn on<const N: usize>(self) -> Option<<T>::At>
where
T: Pick<N>,
{
self.map(T::pick)
}
}
macro_rules! option_of_ref_to_tuple {
($name1:ident, $name2:ident, $as_ref:ident, $AsRef:ident $(, $mut:tt)?) => {
pub trait $name1<'a, T: Tupl> {
fn on<const N: usize>(
self,
) -> Option<<T::$AsRef<'a> as Pick<N>>::At>
where
T::$AsRef<'a>: Pick<N>;
}
impl<'a, T: Tupl> $name1<'a, T> for Option<&'a $($mut)? T> {
fn on<const N: usize>(
self,
) -> Option<<T::$AsRef<'a> as Pick<N>>::At>
where
T::$AsRef<'a>: Pick<N>,
{
match self {
Some(x) => Some(x.$as_ref().pick()),
None => None,
}
}
}
impl<'a, T: Tupl> $name1<'a, T> for &'a $($mut)? Option< T> {
fn on<const N: usize>(
self,
) -> Option<<T::$AsRef<'a> as Pick<N>>::At>
where
T::$AsRef<'a>: Pick<N>,
{
match self {
Some(x) => Some(x.$as_ref().pick()),
None => None,
}
}
}
};
}
option_of_ref_to_tuple!(
OptionOfRefToTuple,
OptionOfRefToTupleWithF,
as_ref,
AsRef
);
option_of_ref_to_tuple!(
OptionOfMutRefToTuple,
OptionOfMutRefToTupleWithF,
as_mut,
AsMut,
mut
);
#[test]
fn x() {
struct Y;
let x = Some(&mut (Y, 2));
let x = x.on::<1>();
let x = &mut Some((Y, 2));
let x = x.on::<1>();
}