use super::property::{
MultipleProperty, MultipleSnapProj, MultipleSnapProjAt, OptionalProperty, OptionalSnapProj,
OptionalSnapProjAt, SingleProperty, SingleSnapProj, SingleSnapProjAt,
};
pub trait MatchResultSingle {
type Snapshot<'a>
where
Self: 'a;
type Properties;
type Output;
fn new() -> Self;
fn new_properties() -> Self::Properties;
fn to_output(self) -> Self::Output;
fn subtract_from_result(&self, result: &mut Self);
fn snapshot(&self) -> Self::Snapshot<'_>;
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a;
}
pub trait MatchResultMultiple {
type Snapshot<'a>
where
Self: 'a;
type Properties;
fn new() -> Self;
fn new_properties() -> Self::Properties;
fn subtract_from_result(&self, result: &mut Self);
fn snapshot(&self) -> Self::Snapshot<'_>;
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a;
}
pub trait MatchResultOptional {
type Snapshot<'a>
where
Self: 'a;
type Properties;
fn new() -> Self;
fn new_properties() -> Self::Properties;
fn subtract_from_result(&self, result: &mut Self);
fn snapshot(&self) -> Self::Snapshot<'_>;
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a;
}
pub trait MatchResult {
type Snapshot<'a>
where
Self: 'a;
type Single: MatchResultSingle;
type Multiple: MatchResultMultiple;
type Optional: MatchResultOptional;
fn new(
match_result_single: Self::Single,
match_result_multiple: Self::Multiple,
match_result_optional: Self::Optional,
) -> Self;
#[inline]
fn new_empty() -> Self
where
Self: Sized,
{
Self::new(
Self::Single::new(),
Self::Multiple::new(),
Self::Optional::new(),
)
}
fn single(&mut self) -> &mut Self::Single;
fn multiple(&mut self) -> &mut Self::Multiple;
fn optional(&mut self) -> &mut Self::Optional;
fn snapshot(&self) -> Self::Snapshot<'_>;
fn subtract_from_result(&self, result: &mut Self);
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a;
fn project_single_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut <Self::Single as MatchResultSingle>::Snapshot<'d>
where
Self: 'd;
fn project_multiple_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut <Self::Multiple as MatchResultMultiple>::Snapshot<'d>
where
Self: 'd;
fn project_optional_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut <Self::Optional as MatchResultOptional>::Snapshot<'d>
where
Self: 'd;
}
impl<MResSingle, MResMultiple, MResOptional> MatchResult
for (MResSingle, MResMultiple, MResOptional)
where
MResSingle: MatchResultSingle,
MResMultiple: MatchResultMultiple,
MResOptional: MatchResultOptional,
{
type Snapshot<'a>
= (
MResSingle::Snapshot<'a>,
MResMultiple::Snapshot<'a>,
MResOptional::Snapshot<'a>,
)
where
Self: 'a;
type Single = MResSingle;
type Multiple = MResMultiple;
type Optional = MResOptional;
#[inline]
fn new(
match_result_single: MResSingle,
match_result_multiple: MResMultiple,
match_result_optional: MResOptional,
) -> Self {
(
match_result_single,
match_result_multiple,
match_result_optional,
)
}
#[inline]
fn single(&mut self) -> &mut MResSingle {
&mut self.0
}
#[inline]
fn multiple(&mut self) -> &mut MResMultiple {
&mut self.1
}
#[inline]
fn optional(&mut self) -> &mut MResOptional {
&mut self.2
}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {
(self.0.snapshot(), self.1.snapshot(), self.2.snapshot())
}
#[inline]
fn subtract_from_result(&self, result: &mut Self) {
self.0.subtract_from_result(result.single());
self.1.subtract_from_result(result.multiple());
self.2.subtract_from_result(result.optional());
}
#[inline]
fn project_single_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut MResSingle::Snapshot<'d>
where
Self: 'd,
{
&mut snap.0
}
#[inline]
fn project_multiple_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut MResMultiple::Snapshot<'d>
where
Self: 'd,
{
&mut snap.1
}
#[inline]
fn project_optional_snapshot_mut<'a, 'd>(
snap: &'a mut Self::Snapshot<'d>,
) -> &'a mut MResOptional::Snapshot<'d>
where
Self: 'd,
{
&mut snap.2
}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
(
MResSingle::new_empty_snapshot(),
MResMultiple::new_empty_snapshot(),
MResOptional::new_empty_snapshot(),
)
}
}
impl MatchResultSingle for () {
type Snapshot<'a>
= ()
where
Self: 'a;
type Properties = ();
type Output = ();
#[inline]
fn new() -> Self {}
#[inline]
fn new_properties() -> Self::Properties {}
#[inline]
fn to_output(self) -> Self::Output {}
#[inline]
fn subtract_from_result(&self, _result: &mut Self) {}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
}
}
impl MatchResultMultiple for () {
type Snapshot<'a>
= ()
where
Self: 'a;
type Properties = ();
#[inline]
fn new() -> Self {}
#[inline]
fn new_properties() -> Self::Properties {}
#[inline]
fn subtract_from_result(&self, _result: &mut Self) {}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
}
}
impl MatchResultOptional for () {
type Snapshot<'a>
= ()
where
Self: 'a;
type Properties = ();
#[inline]
fn new() -> Self {}
#[inline]
fn new_properties() -> Self::Properties {}
#[inline]
fn subtract_from_result(&self, _result: &mut Self) {}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
}
}
#[inline]
fn unwrap_single<T>(option: Option<T>) -> T {
option.expect("Expected single match result to be set, but it was not")
}
macro_rules! __impl_snap_projs_recurse {
(
$bucket_single:ty,
$bucket_multiple:ty,
$bucket_optional:ty,
[$($Tall:ident),+],
[]
) => {};
(
$bucket_single:ty,
$bucket_multiple:ty,
$bucket_optional:ty,
[$($Tall:ident),+],
[($Thead:ident, $idxhead:tt) $(, ($Trest:ident, $idxrest:tt))*]
) => {
impl<$($Tall),+> SingleSnapProj<$bucket_single, $Thead> for SingleSnapProjAt<$idxhead> {
#[inline]
fn project<'a, 'd>(
&self,
snap: &'a mut <$bucket_single as MatchResultSingle>::Snapshot<'d>,
) -> &'a mut Option<&'d $Thead>
where
$bucket_single: 'd,
{
&mut snap.$idxhead
}
}
impl<$($Tall),+> MultipleSnapProj<$bucket_multiple, $Thead> for MultipleSnapProjAt<$idxhead> {
#[inline]
fn project<'a, 'd>(
&self,
snap: &'a mut <$bucket_multiple as MatchResultMultiple>::Snapshot<'d>,
) -> &'a mut Vec<&'d $Thead>
where
$bucket_multiple: 'd,
{
&mut snap.$idxhead
}
}
impl<$($Tall),+> OptionalSnapProj<$bucket_optional, $Thead> for OptionalSnapProjAt<$idxhead> {
#[inline]
fn project<'a, 'd>(
&self,
snap: &'a mut <$bucket_optional as MatchResultOptional>::Snapshot<'d>,
) -> &'a mut Option<&'d $Thead>
where
$bucket_optional: 'd,
{
&mut snap.$idxhead
}
}
__impl_snap_projs_recurse! {
$bucket_single,
$bucket_multiple,
$bucket_optional,
[$($Tall),+],
[$(($Trest, $idxrest)),*]
}
};
}
macro_rules! impl_match_results_for_tuple {
( $(($T:ident, $idx:tt)),+ ) => {
impl<$($T),+> MatchResultSingle for ($(Option<$T>,)+)
{
type Snapshot<'a>
= ($(Option<&'a $T>,)+)
where
Self: 'a;
type Properties = (
$(SingleProperty<
fn(&mut Self) -> &mut Option<$T>,
SingleSnapProjAt<$idx>,
>,)+
);
type Output = ($($T,)+);
#[inline]
fn new() -> Self {
($( { let _: std::marker::PhantomData<$T>; None },)+ )
}
#[inline]
fn new_properties() -> Self::Properties {
($(
SingleProperty::new(
(|s: &mut Self| -> &mut Option<$T> { &mut s.$idx })
as fn(&mut Self) -> &mut Option<$T>,
SingleSnapProjAt::<$idx>,
),
)+)
}
#[inline]
fn to_output(self) -> Self::Output {
#[allow(non_snake_case)]
let ($( $T, )+) = self;
($(unwrap_single($T),)+)
}
#[inline]
fn subtract_from_result(&self, result: &mut Self) {
$(if self.$idx.is_some() {
result.$idx = None;
})+;
}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {
($(self.$idx.as_ref(),)+)
}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
($(None::<&'a $T>,)+)
}
}
impl<$($T),+> MatchResultMultiple for ($(Vec<$T>,)+) {
type Snapshot<'a>
= ($(Vec<&'a $T>,)+)
where
Self: 'a;
type Properties = (
$(MultipleProperty<
fn(&mut Self) -> &mut Vec<$T>,
MultipleSnapProjAt<$idx>,
>,)+
);
#[inline]
fn new() -> Self {
($( { let _: std::marker::PhantomData<$T>; Vec::new() },)+ )
}
#[inline]
fn new_properties() -> Self::Properties {
($(
MultipleProperty::new(
(|s: &mut Self| -> &mut Vec<$T> { &mut s.$idx })
as fn(&mut Self) -> &mut Vec<$T>,
MultipleSnapProjAt::<$idx>,
),
)+)
}
#[inline]
fn subtract_from_result(&self, result: &mut Self) {
$(
{
let n = self.$idx.len();
result.$idx.truncate(result.$idx.len() - n);
}
)+;
}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {
($(self.$idx.iter().collect::<Vec<&$T>>(),)+)
}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
($(Vec::<&'a $T>::new(),)+)
}
}
impl<$($T),+> MatchResultOptional for ($(Option<$T>,)+) {
type Snapshot<'a>
= ($(Option<&'a $T>,)+)
where
Self: 'a;
type Properties = (
$(OptionalProperty<
fn(&mut Self) -> &mut Option<$T>,
OptionalSnapProjAt<$idx>,
>,)+
);
#[inline]
fn new() -> Self {
($( { let _: std::marker::PhantomData<$T>; None },)+ )
}
#[inline]
fn new_properties() -> Self::Properties {
($(
OptionalProperty::new(
(|s: &mut Self| -> &mut Option<$T> { &mut s.$idx })
as fn(&mut Self) -> &mut Option<$T>,
OptionalSnapProjAt::<$idx>,
),
)+)
}
#[inline]
fn subtract_from_result(&self, result: &mut Self) {
$(if self.$idx.is_some() {
result.$idx = None;
})+;
}
#[inline]
fn snapshot(&self) -> Self::Snapshot<'_> {
($(self.$idx.as_ref(),)+)
}
#[inline]
fn new_empty_snapshot<'a>() -> Self::Snapshot<'a>
where
Self: 'a,
{
($(None::<&'a $T>,)+)
}
}
__impl_snap_projs_recurse! {
($(Option<$T>,)+),
($(Vec<$T>,)+),
($(Option<$T>,)+),
[$($T),+],
[$(($T, $idx)),+]
}
};
}
impl_match_results_for_tuple!((T0, 0));
impl_match_results_for_tuple!((T0, 0), (T1, 1));
impl_match_results_for_tuple!((T0, 0), (T1, 1), (T2, 2));
impl_match_results_for_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3));
impl_match_results_for_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4));
impl_match_results_for_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5));
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6)
);
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7)
);
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8)
);
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8),
(T9, 9)
);
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8),
(T9, 9),
(T10, 10)
);
impl_match_results_for_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8),
(T9, 9),
(T10, 10),
(T11, 11)
);