ql.rs/src/macros.rs

457 lines
12 KiB
Rust

use paste;
#[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.
(@ $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 {
(@
$(
$(#[$meta:meta])
*
$vis:vis $data:ident$((
$(#[$def_meta:meta])
+
))? {
$(
$( #[$variant_meta:meta] )*
$variant:ident$((
$(#[$variant_def_meta:meta])
+
))? {
$(
$(#[$field_meta:meta])
*
$field:ident: $($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>];
// )+
// }
$(
#[derive(Debug, Clone, Copy, Default)]
$( $( #[$variant_def_meta] )+ )?
$vis struct [<$data Def Variant $variant>] {
$(
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) {
match self {
$(
Self::$variant { $( ref mut $field ),+ } => {
let def = $crate::paste::paste! { &def.[<$variant:snake:lower>] };
$(
let query = &def.$field;
$crate::query_def_filter!(@ query, $field, $($qualifier)? ($($type)+));
)
+
}
)+
}
}
}
)
*
};
}
/// Defines a dynamic query structure.
#[cfg(not(feature = "serde"))]
#[macro_export]
macro_rules! query_def_struct {
(
$(
$(#[$meta:meta])
*
$vis:vis $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)+),
)+
}
)
*
);
};
}
/// Defines a dynamic enumerated query structure.
#[cfg(not(feature = "serde"))]
#[macro_export]
macro_rules! query_def_enum {
(
$(
$(#[$meta:meta])
*
$vis:vis $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)+),
)+
}
),+
}
)
*
);
};
}
/// Defines a dynamic query structure.
#[cfg(feature = "serde")]
#[macro_export]
macro_rules! query_def_struct {
(
$(
$(#[$meta:meta])
*
$vis:vis $data:ident$((
$(#[$def_meta:meta])
+
))? {
$(
$(#[$field_meta:meta])
*
$field:ident: $($qualifier:lifetime)? ($($type:tt)+),
)+
}
)
*
) => {
$crate::query_def_internal_struct!(@
$(
#[derive(Serialize, Deserialize)]
$(#[$meta])
*
$vis $data(
#[derive(Serialize, Deserialize)]
#[serde(default)]
$(
$(#[$def_meta])
+
)?
) {
$(
#[serde(skip_serializing_if = "Option::is_none")]
$(#[$field_meta])
*
$field: $($qualifier)? ($($type)+),
)+
}
)
*
);
};
}
/// Defines a dynamic enumerated query structure.
#[cfg(feature = "serde")]
#[macro_export]
macro_rules! query_def_enum {
(
$(
$(#[$meta:meta])
*
$vis:vis $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(Serialize, Deserialize)]
$(#[$meta])
*
$vis $data(
#[derive(Serialize, Deserialize)]
#[serde(default)]
$(
$(#[$def_meta])
+
)?
) {
$(
$(#[$variant_meta])
*
$variant(
#[derive(Serialize, Deserialize)]
#[serde(default)]
$(
$(#[$variant_def_meta])
+
)?
) {
$(
#[serde(skip_serializing_if = "Option::is_none")]
$(#[$field_meta])
*
$field: $($qualifier)? ($($type)+),
)+
}
),+
}
)
*
);
};
}