#[macro_export]
macro_rules! property_stub {
($ctxs:ident, $token_variant:path $(| $other_variant:path)*, $token:ident, $impl:block) => {
Box::new($ctxs.map(move |ctx| {
let value = match &ctx.current_token {
Some($token_variant($token)) => $impl,
$( Some($other_variant($token)) => $impl, )*
None => FieldValue::Null,
#[allow(unreachable_patterns)]
Some(x) => {
unreachable!(
"Unexpected token variant encountered! Expecting {:?} but got {:?}",
stringify!($token_variant $(| $other_variant)*),
x
);
}
};
(ctx, value)
}))
};
}
#[macro_export]
macro_rules! property_group {
($ctxs:ident, $field_name:ident, $token_variant:path $(| $other_variant:path)*,
[
$($rest:tt),+ $(,)?
] $(,)?
) => {
$crate::property_group!( @( $ctxs; $field_name; $token_variant $(| $other_variant)*; $($rest)+ ), )
};
(@($ctxs:ident; $field_name:ident; $token_variant:path $(| $other_variant:path)*;
$prop_and_field:ident $($rest:tt)*
), $($arms:tt)*) => {
$crate::property_group!(
@($ctxs; $field_name; $token_variant $(| $other_variant)*; $($rest)*),
$($arms)*
stringify!($prop_and_field) => {
$crate::property_stub!($ctxs, $token_variant $(| $other_variant)*, token, {
token.$prop_and_field.clone().into()
})
}
)
};
(@($ctxs:ident; $field_name:ident; $token_variant:path $(| $other_variant:path)*;
($prop_name:ident, $field:ident $(,)? ) $($rest:tt)*
), $($arms:tt)*) => {
$crate::property_group!(
@($ctxs; $field_name; $token_variant $(| $other_variant:path)*; $($rest)*),
$($arms)*
stringify!($prop_name) => {
$crate::property_stub!($ctxs, $token_variant $(| $other_variant)*, token, {
token.$field.clone().into()
})
}
)
};
(@($ctxs:ident; $field_name:ident; $token_variant:path $(| $other_variant:path)*;
($prop_name:ident, $token:ident, $impl:block $(,)? ) $($rest:tt)*
), $($arms:tt)*) => {
$crate::property_group!(
@($ctxs; $field_name; $token_variant $(| $other_variant)*; $($rest)*),
$($arms)*
stringify!($prop_name) => {
$crate::property_stub!($ctxs, $token_variant $(| $other_variant)*, $token, $impl)
}
)
};
(@($ctxs:ident; $field_name:ident; $token_variant:path $(| $other_variant:path)*; ),
$($arms:tt)+
) => {
match $field_name.as_ref() {
$($arms)+
_ => unreachable!(
"Unexpected property name {} for token variant {:?}",
$field_name.as_ref(), stringify!($token_variant $(| $other_variant:path)*)
),
}
}
}
#[macro_export]
macro_rules! project_property {
($ctxs:ident, $type_name:ident, $field_name:ident,
[
$(
{
$type_option:ident $(| $other_type_option:ident)*,
$token_variant:path $(| $other_variant:path)*,
[ $($rest:tt),+ $(,)? ] $(,)?
}
),+ $(,)?
] $(,)?
) => {
match $type_name.as_ref() {
$(
stringify!($type_option) $(| stringify!($other_type_option))* => {
$crate::property_group!($ctxs, $field_name, $token_variant $(| $other_variant)*, [ $($rest),+ ])
}
)+
_ => unreachable!(
"Unexpected type name {}", $type_name.as_ref()
),
}
};
}
#[macro_export]
macro_rules! neighbor_stub {
($ctxs:ident, $lt:lifetime, $token_variant:path $(| $other_variant:path)*, $token:ident, $impl:tt) => {
Box::new($ctxs.map(move |ctx| {
let neighbors: Box<dyn Iterator<Item = Self::DataToken> + $lt> =
match &ctx.current_token {
Some($token_variant($token)) => $impl,
$( Some($other_variant($token)) => $impl, )*
None => Box::new(std::iter::empty()),
#[allow(unreachable_patterns)]
Some(x) => {
unreachable!(
"Unexpected token variant encountered! Expecting {} but got {:?}",
stringify!($token_variant $(| $other_variant)*),
x
);
}
};
(ctx, neighbors)
}))
};
}
#[macro_export]
macro_rules! neighbor_group {
($ctxs:ident, $lt:lifetime, $edge_name_var:ident, $token_variant:path $(| $other_variant:path)*,
[
$($rest:tt),+ $(,)?
] $(,)?
) => {
$crate::neighbor_group!( @( $ctxs; $lt; $edge_name_var; $token_variant $(| $other_variant)*; $($rest)+ ), )
};
(@($ctxs:ident; $lt:lifetime; $edge_name_var:ident; $token_variant:path $(| $other_variant:path)*;
(
$edge_and_field:ident,
$next_variant:path $(,)?
) $($rest:tt)*
), $($arms:tt)*) => {
$crate::neighbor_group!(
@($ctxs; $lt; $edge_name_var; $token_variant $(| $other_variant)*; $($rest)*),
$($arms)*
stringify!($edge_and_field) => {
$crate::neighbor_stub!($ctxs, $lt, $token_variant, token, {
Box::new(token.$edge_and_field.iter().map($next_variant))
})
}
)
};
(@($ctxs:ident; $lt:lifetime; $edge_name_var:ident; $token_variant:path $(| $other_variant:path)*;
(
$edge_name:ident,
$field:ident,
$next_variant:path $(,)?
) $($rest:tt)*
), $($arms:tt)*) => {
$crate::neighbor_group!(
@($ctxs; $lt; $edge_name_var; $token_variant $(| $other_variant)*; $($rest)*),
$($arms)*
stringify!($edge_name) => {
$crate::neighbor_stub!($ctxs, $lt, $token_variant $(| $other_variant)*, token, {
Box::new(token.$field.iter().map($next_variant))
})
}
)
};
(@($ctxs:ident; $lt:lifetime; $edge_name_var:ident; $token_variant:path $(| $other_variant:path)*;
(
$edge_name:ident,
$token:ident,
$impl:block $(,)?
) $($rest:tt)*
), $($arms:tt)*) => {
$crate::neighbor_group!(
@($ctxs; $lt; $edge_name_var; $token_variant $(| $other_variant)*; $($rest)*),
$($arms)*
stringify!($edge_name) => {
$crate::neighbor_stub!($ctxs, $lt, $token_variant $(| $other_variant)*, $token, $impl)
}
)
};
(@($ctxs:ident; $lt:lifetime; $edge_name_var:ident; $token_variant:path $(| $other_variant:path)*; ),
$($arms:tt)+
) => {
match $edge_name_var.as_ref() {
$($arms)+
_ => unreachable!(
"Unexpected edge name {} for token variant {:?}",
$edge_name_var.as_ref(), stringify!($token_variant $(| $other_variant)*)
),
}
}
}
#[macro_export]
macro_rules! project_neighbors {
($ctxs:ident, $lt:lifetime, $type_name_var:ident, $edge_name_var:ident,
[
$(
{
$type_option:ident $(| $other_type_option:ident)*,
$token_variant:path $(| $other_variant:path)*,
[ $($rest:tt),+ $(,)? ] $(,)?
}
),+ $(,)?
] $(,)?
) => {
match $type_name_var.as_ref() {
$(
stringify!($type_option) $(| stringify!($other_type_option))* => {
$crate::neighbor_group!($ctxs, $lt, $edge_name_var, $token_variant $(| $other_variant)*, [ $($rest),+ ])
}
)+
_ => unreachable!(
"Unexpected type name {}", $type_name_var.as_ref()
),
}
};
}
#[macro_export]
macro_rules! project_neighbors2_match_arm {
($ctxs:ident, $lt:lifetime, $edge_name:ident, $token_variant:path $(| $other_variant:path)*, $next_variant:path $(,)?) => {
$crate::neighbor_stub!(
$ctxs, $lt, $token_variant $(| $other_variant)*, token, {
Box::new(token.$edge_name.iter().map($next_variant))
}
)
};
($ctxs:ident, $lt:lifetime, $edge_name:ident, $token_variant:path $(| $other_variant:path)*, ($field:ident, $next_variant:path $(,)?) $(,)?) => {
$crate::neighbor_stub!(
$ctxs, $lt, $token_variant $(| $other_variant)*, token, {
Box::new(token.$field.iter().map($next_variant))
}
)
};
($ctxs:ident, $lt:lifetime, $edge_name:ident, $token_variant:path $(| $other_variant:path)*, ($token:ident, $impl:block $(,)?) $(,)?) => {
$crate::neighbor_stub!($ctxs, $lt, $token_variant $(| $other_variant)*, $token, $impl)
};
}
#[macro_export]
macro_rules! project_neighbors2 {
($ctxs:ident, $lt:lifetime, $type_name_var:ident, $edge_name_var:ident,
[
$(
{
$type_option:ident $(| $other_type_option:ident)*,
$edge_name:ident,
$token_variant:path $(| $other_variant:path)*,
$rest:tt $(,)?
}
),+ $(,)?
] $(,)?
) => {
match ($edge_name_var.as_ref(), $type_name_var.as_ref()) {
$(
(stringify!($edge_name), stringify!($type_option)) $(| (stringify!($edge_name), stringify!($other_type_option)))* => {
$crate::project_neighbors2_match_arm!($ctxs, $lt, $edge_name, $token_variant $(| $other_variant)*, $rest )
}
)+
_ => unreachable!(
"Unexpected type and edge name {} {}", $type_name_var.as_ref(), $edge_name_var.as_ref(),
),
}
};
}