#[macro_export]
macro_rules! field {
( $($tt:tt)* ) => {{
$crate::field_check_helper! { $($tt)* }
$crate::field_string_helper! { $($tt)* }
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! field_string_helper {
( $field:ident in $type:path ) => {
stringify!($field)
};
( @ $field:ident in $type:path ) => {
concat!( "$", stringify!($field) )
};
( @ @ $field:ident in $type:path ) => {
concat!( "$$", stringify!( $field ) )
};
( ( $field:ident in $type:path ) ) => {
stringify!($field)
};
( ( $field:ident in $type:path ) $( . $rest:tt )+ ) => {
concat!( stringify!($field), ".", $crate::field_string_helper!($($rest).+) )
};
( @ ( $field:ident in $type:path ) $( . $rest:tt )+ ) => {
concat!( "$", stringify!($field), ".", $crate::field_string_helper!($($rest).+) )
};
( @ @ ( $field:ident in $type:path ) $( . $rest:tt )+ ) => {
concat!( "$$", stringify!($field), ".", $crate::field_string_helper!($($rest).+) )
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! field_check_helper {
( $field:ident in $type:path ) => {
#[allow(unknown_lints, unneeded_field_pattern)]
const _: fn() = || {
let $type { $field: _, .. };
};
};
( @ $field:ident in $type:path ) => { $crate::field_check_helper!($field in $type) };
( @ @ $field:ident in $type:path ) => { $crate::field_check_helper!($field in $type) };
( ( $field:ident in $type:path ) ) => { $crate::field_check_helper!($field in $type) };
( @ ( $field:ident in $type:path ) ) => { $crate::field_check_helper!($field in $type) };
( @ @ ( $field:ident in $type:path ) ) => { $crate::field_check_helper!($field in $type) };
( ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) ) => {
#[allow(unknown_lints, unneeded_field_pattern)]
const _: fn($type) = |a: $type| {
let takes_type2 = |_: $type2| {};
takes_type2(a.$field);
};
$crate::field_check_helper!($field in $type);
$crate::field_check_helper!($field2 in $type2);
};
( ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) . $($rest:tt)+ ) => {
#[allow(unknown_lints, unneeded_field_pattern)]
const _: fn($type) = |a: $type| {
let takes_type2 = |_: $type2| {};
takes_type2(a.$field);
};
$crate::field_check_helper!($field in $type);
$crate::field_check_helper!(( $field2 in $type2 ) . $($rest)+)
};
( @ ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) ) => {
$crate::field_check_helper!(( $field in $type ) . ( $field2 in $type2 ) )
};
( @ ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) . $($rest:tt)+ ) => {
$crate::field_check_helper!(( $field in $type ) . ( $field2 in $type2 ) . $($rest)+ )
};
( @ @ ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) ) => {
$crate::field_check_helper!(( $field in $type ) . ( $field2 in $type2 ) )
};
( @ @ ( $field:ident in $type:path ) . ( $field2:ident in $type2:path ) . $($rest:tt)+ ) => {
$crate::field_check_helper!(( $field in $type ) . ( $field2 in $type2 ) . $($rest)+ )
};
}
#[macro_export]
macro_rules! f {
( $($tt:tt)* ) => {{
$crate::field_check_helper! { $($tt)* }
$crate::field_string_helper! { $($tt)* }
}};
}
#[macro_export]
macro_rules! pipeline {
($($tt:tt)*)=> {{
let mut vec = vec![];
$crate::pipeline_helper!(vec $($tt)*);
vec
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! pipeline_helper {
($vec:ident $key:ident : $value:tt ,) => {
$vec.push($crate::mongo::bson::doc! { $key : $value });
};
($vec:ident $key:ident : $value:tt) => {
$vec.push($crate::mongo::bson::doc! { $key : $value });
};
($vec:ident $key:ident : $value:tt , $($rest:tt)*) => {{
$vec.push($crate::mongo::bson::doc! { $key : $value });
$crate::pipeline_helper!($vec $($rest)*);
}};
($vec:ident $stage:expr ,) => {
$vec.push($crate::mongo::bson::Document::from($stage));
};
($vec:ident $stage:expr) => {
$vec.push($crate::mongo::bson::Document::from($stage));
};
($vec:ident $stage:expr , $($rest:tt)*) => {{
$vec.push($crate::mongo::bson::Document::from($stage));
$crate::pipeline_helper!($vec $($rest)*);
}};
}