424 lines
12 KiB
Rust
424 lines
12 KiB
Rust
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_type {
|
|
(($type:ty)) => {
|
|
$type
|
|
};
|
|
('dyn ($type:ty)) => {
|
|
$type
|
|
};
|
|
('vec ($type:ty)) => {
|
|
::std::vec::Vec<$type>
|
|
};
|
|
('map ($key:ty, $value:ty)) => {
|
|
::std::collections::HashMap<$key, $value>
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_field {
|
|
(@dyn $type:ty) => {
|
|
Option<<$type as $crate::DynamicQuery>::Definition>
|
|
};
|
|
(($type:ty)) => {
|
|
bool
|
|
};
|
|
('dyn ($type:ty)) => {
|
|
$crate::query_def_field!(@dyn $type)
|
|
};
|
|
('vec ($type:ty)) => {
|
|
$crate::query_def_field!(@dyn $type)
|
|
};
|
|
('map ($key:ty, $value:ty)) => {
|
|
$crate::query_def_field!(@dyn $value)
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_filter {
|
|
// note about this: 'dyn is implied for 'vec and 'map because if the type is not 'dyn, then the
|
|
// special handling is not necessary in the first place (i.e. you can just do `(Vec<Type>)`
|
|
// instead of `'vec (Type)`.
|
|
($query:expr, $value:ident, 'vec ($_type:path)) => {
|
|
match $query {
|
|
Some(query) => {
|
|
if let Some(ref mut value) = $value {
|
|
for value in value.iter_mut() {
|
|
value.filter_ref(&query);
|
|
}
|
|
}
|
|
}
|
|
None => {
|
|
*$value = None;
|
|
}
|
|
}
|
|
};
|
|
($query:expr, $value:ident, 'map ($_key:path, $_value:path)) => {
|
|
match $query {
|
|
Some(query) => {
|
|
if let Some(ref mut value) = $value {
|
|
for (_, value) in value.iter_mut() {
|
|
value.filter_ref(&query);
|
|
}
|
|
}
|
|
}
|
|
None => {
|
|
*$value = None;
|
|
}
|
|
}
|
|
};
|
|
($query:expr, $value:ident, 'dyn ($($_type:tt)+)) => {
|
|
if let Some(ref mut value) = $value {
|
|
if let Some(ref query) = $query {
|
|
value.filter_ref(&query);
|
|
}
|
|
}
|
|
};
|
|
($query:expr, $value:ident, ($($_type:tt)+)) => {
|
|
if !*$query {
|
|
*$value = None;
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_internal_struct {
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
}
|
|
) => {
|
|
#[derive(Debug, Clone)]
|
|
$( #[$meta] )*
|
|
$vis struct $data {
|
|
$(
|
|
$( #[$field_meta] )*
|
|
pub $field: Option<$crate::query_def_type!($( $qualifier )? ($( $type )+))>
|
|
),+
|
|
}
|
|
|
|
$crate::paste::paste! {
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
$( $( #[$def_meta] )+ )?
|
|
$vis struct [<$data Def>] {
|
|
$( pub $field: $crate::query_def_field!($( $qualifier )? ($( $type )+)) ),+
|
|
}
|
|
}
|
|
|
|
impl $crate::DynamicQuery for $data {
|
|
type Definition = $crate::paste::paste! { [<$data Def>] };
|
|
|
|
fn filter_ref(&mut self, def: &Self::Definition) {
|
|
$(
|
|
let query = &def.$field;
|
|
let value = &mut self.$field;
|
|
$crate::query_def_filter!(query, value, $( $qualifier )? ($( $type )+));
|
|
)+
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_internal_enum_variant_def {
|
|
(
|
|
$( #[$variant_def_meta:meta] )*
|
|
$vis:vis $name:ident
|
|
) => {
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
$( #[$variant_def_meta] )*
|
|
$vis struct $name;
|
|
};
|
|
(
|
|
$( #[$variant_def_meta:meta] )*
|
|
$vis:vis $name:ident {
|
|
$( $field:ident$((
|
|
$( #[$variant_def_field_meta:meta] )+
|
|
))?: $( $qualifier:lifetime )? ($( $type:tt )+) ),+
|
|
}
|
|
) => {
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
$( #[$variant_def_meta] )*
|
|
$vis struct $name {
|
|
$(
|
|
$( $( #[$variant_def_field_meta] )+ )?
|
|
pub $field: $crate::query_def_field!($( $qualifier )? ($( $type )+))
|
|
),+
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_internal_enum {
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$variant_meta:meta] )*
|
|
$variant:ident$((
|
|
$( #[$variant_def_meta:meta] )+
|
|
))? $({
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident$((
|
|
$( #[$variant_def_field_meta:meta] )+
|
|
))?: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
) => {
|
|
#[derive(Debug, Clone)]
|
|
$( #[$meta] )*
|
|
$vis enum $data {
|
|
$(
|
|
$( #[$variant_meta] )*
|
|
$variant $({
|
|
$(
|
|
$( #[$field_meta] )*
|
|
$field: Option<$crate::query_def_type!($( $qualifier )? ($( $type )+))>
|
|
),*
|
|
})?
|
|
),+
|
|
}
|
|
|
|
$crate::paste::paste! {
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
$( $( #[$def_meta] )+ )?
|
|
$vis struct [<$data Def>] {
|
|
$( pub [<$variant:snake:lower>]: [<$data Def Variant $variant>] ),+
|
|
}
|
|
}
|
|
|
|
// $crate::paste::paste! {
|
|
// impl [<$data Def>] {
|
|
// $(
|
|
// pub type $variant = [<$data Def Variant $variant>];
|
|
// )+
|
|
// }
|
|
// }
|
|
|
|
$crate::paste::paste! {
|
|
$(
|
|
$crate::query_def_internal_enum_variant_def! {
|
|
$( $( #[$variant_def_meta] )+ )?
|
|
$vis [<$data Def Variant $variant>] $({
|
|
$( $field$((
|
|
$( #[$variant_def_field_meta] )+
|
|
))?: $( $qualifier )? ($( $type )+) ),+
|
|
})?
|
|
}
|
|
)+
|
|
}
|
|
|
|
impl $crate::DynamicQuery for $data {
|
|
type Definition = $crate::paste::paste! { [<$data Def>] };
|
|
|
|
fn filter_ref(&mut self, def: &Self::Definition) {
|
|
match self {
|
|
$(
|
|
Self::$variant $({ $( ref mut $field ),* })? => {
|
|
$($(
|
|
let query = &$crate::paste::paste! { &def.[<$variant:snake:lower>] }.$field;
|
|
$crate::query_def_filter!(query, $field, $( $qualifier )? ($( $type )+));
|
|
)*)?
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(not(feature = "serde"))]
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_0 {
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis struct $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
|
|
$(,)?
|
|
}
|
|
) => {
|
|
$crate::query_def_internal_struct! {
|
|
$( #[$meta] )*
|
|
$vis $data$((
|
|
$( #[$def_meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$field_meta] )*
|
|
$field: $( $qualifier )? ($( $type )+)
|
|
),+
|
|
}
|
|
}
|
|
};
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis enum $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$variant_meta:meta] )*
|
|
$variant:ident$((
|
|
$( #[$variant_def_meta:meta] )+
|
|
))? $({
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
|
|
$(,)?
|
|
})?
|
|
),+
|
|
|
|
$(,)?
|
|
}
|
|
) => {
|
|
$crate::query_def_internal_enum! {
|
|
$( #[$meta] )*
|
|
$vis $data$((
|
|
$( #[$def_meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$variant_meta] )*
|
|
$variant$((
|
|
$( #[$variant_def_meta] )?
|
|
))? $({
|
|
$(
|
|
$( #[$field_meta] )*
|
|
$field: $( $qualifier )? ($( $type )+)
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(feature = "serde")]
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! query_def_0 {
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis struct $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
|
|
$(,)?
|
|
}
|
|
) => {
|
|
$crate::query_def_internal_struct! {
|
|
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
|
|
$( #[$meta] )*
|
|
$vis $data(
|
|
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
|
|
#[serde(default)]
|
|
$( $( #[$def_meta] )+ )?
|
|
) {
|
|
$(
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
$( #[$field_meta] )*
|
|
$field: $( $qualifier )? ($( $type )+)
|
|
),+
|
|
}
|
|
}
|
|
};
|
|
(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis enum $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$(
|
|
$( #[$variant_meta:meta] )*
|
|
$variant:ident$((
|
|
$( #[$variant_def_meta:meta] )+
|
|
))? $({
|
|
$(
|
|
$( #[$field_meta:meta] )*
|
|
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
|
|
),+
|
|
|
|
$(,)?
|
|
})?
|
|
),+
|
|
|
|
$(,)?
|
|
}
|
|
) => {
|
|
$crate::query_def_internal_enum! {
|
|
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
|
|
$( #[$meta] )*
|
|
$vis $data(
|
|
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
|
|
#[serde(default)]
|
|
$( $( #[$def_meta] )+ )?
|
|
) {
|
|
$(
|
|
$( #[$variant_meta] )*
|
|
$variant(
|
|
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
|
|
$( $( #[$variant_def_meta] )+ )?
|
|
) $({
|
|
$(
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
$( #[$field_meta] )*
|
|
$field(
|
|
#[serde(default)]
|
|
): $( $qualifier )? ($( $type )+)
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Defines a dynamic query structure.
|
|
///
|
|
/// See the crate documentation for details.
|
|
#[macro_export]
|
|
macro_rules! query_def {
|
|
($(
|
|
$( #[$meta:meta] )*
|
|
$vis:vis $type:ident $data:ident$((
|
|
$( #[$def_meta:meta] )+
|
|
))? {
|
|
$($body:tt)+
|
|
}
|
|
)*) => {
|
|
$($crate::query_def_0! {
|
|
$( #[$meta] )*
|
|
$vis $type $data$((
|
|
$( #[$def_meta] )+
|
|
))? {
|
|
$($body)+
|
|
}
|
|
})*
|
|
};
|
|
}
|