Enum support, use paste to generate definition struct names
This commit is contained in:
parent
bde3ce5cce
commit
4c6aadf634
40
src/lib.rs
40
src/lib.rs
|
@ -4,6 +4,7 @@ pub trait DynamicQuery {
|
|||
|
||||
fn filter_ref(&mut self, def: &Self::Definition);
|
||||
|
||||
#[inline(always)]
|
||||
fn filter(mut self, def: &Self::Definition) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -19,10 +20,13 @@ mod macros;
|
|||
mod tests {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::DynamicQuery;
|
||||
|
||||
// just tests that the macro compiles
|
||||
crate::query_def! {
|
||||
crate::query_def_struct! {
|
||||
/// Foo doc.
|
||||
Foo(FooDef) {
|
||||
#[derive(PartialEq)]
|
||||
Foo {
|
||||
/// Field doc.
|
||||
#[serde(flatten)]
|
||||
bar: (Bar),
|
||||
|
@ -32,21 +36,47 @@ mod tests {
|
|||
}
|
||||
|
||||
/// Bar doc.
|
||||
Bar(BarDef) {
|
||||
#[derive(PartialEq)]
|
||||
Bar {
|
||||
baz_inner: (bool),
|
||||
}
|
||||
}
|
||||
|
||||
crate::query_def_enum! {
|
||||
FooOrBar {
|
||||
Foo {
|
||||
value: 'dyn (Foo),
|
||||
},
|
||||
|
||||
Bar {
|
||||
value: 'dyn (Bar),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure A. serde is working and B. we get expected structure
|
||||
#[test]
|
||||
fn test_json() {
|
||||
assert_eq!(serde_json::to_string(&Foo {
|
||||
let x = Foo {
|
||||
bar: Some(Bar {
|
||||
baz_inner: Some(true),
|
||||
}),
|
||||
baz: Some(false),
|
||||
bars: Some(vec![]),
|
||||
bars_by_bazs: Some(std::collections::HashMap::new()),
|
||||
}).ok(), Some(r#"{"baz_inner":true,"baz":false,"bars":[],"bars_by_bazs":{}}"#.to_owned()));
|
||||
};
|
||||
assert_eq!(serde_json::to_string(&x).ok(), Some(r#"{"baz_inner":true,"baz":false,"bars":[],"bars_by_bazs":{}}"#.to_owned()));
|
||||
|
||||
assert_eq!(x.clone().filter(&FooDef {
|
||||
bar: false,
|
||||
baz: true,
|
||||
bars: Some(BarDef::default()),
|
||||
bars_by_bazs: None,
|
||||
}), Foo {
|
||||
bar: None,
|
||||
baz: Some(false),
|
||||
bars: Some(vec![]),
|
||||
bars_by_bazs: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
289
src/macros.rs
289
src/macros.rs
|
@ -7,7 +7,7 @@ macro_rules! query_def_type {
|
|||
$type
|
||||
};
|
||||
(@ 'vec ($type:ty)) => {
|
||||
Vec<$type>
|
||||
::std::vec::Vec<$type>
|
||||
};
|
||||
(@ 'map ($key:ty, $value:ty)) => {
|
||||
::std::collections::HashMap<$key, $value>
|
||||
|
@ -80,16 +80,15 @@ macro_rules! query_def_filter {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! query_def_internal {
|
||||
macro_rules! query_def_internal_struct {
|
||||
(@
|
||||
$(
|
||||
$(#[$meta:meta])
|
||||
*
|
||||
$vis:vis $data:ident(
|
||||
$vis:vis $data:ident$((
|
||||
$(#[$def_meta:meta])
|
||||
*
|
||||
$def:ident
|
||||
) {
|
||||
+
|
||||
))? {
|
||||
$(
|
||||
$(#[$field_meta:meta])
|
||||
*
|
||||
|
@ -111,17 +110,18 @@ macro_rules! query_def_internal {
|
|||
)+
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
$(#[$def_meta])
|
||||
*
|
||||
$vis struct $def {
|
||||
$(
|
||||
pub $field: $crate::query_def_field!(@ $($qualifier)? ($($type)+)),
|
||||
)+
|
||||
::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 = $def;
|
||||
type Definition = ::paste::paste! { [<$data Def>] };
|
||||
|
||||
fn filter_ref(&mut self, def: &Self::Definition) {
|
||||
$(
|
||||
|
@ -137,19 +137,113 @@ macro_rules! query_def_internal {
|
|||
};
|
||||
}
|
||||
|
||||
#[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)+))>,
|
||||
)+
|
||||
}
|
||||
),+
|
||||
}
|
||||
|
||||
::paste::paste! {
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
$( $( #[$def_meta] )+ )?
|
||||
$vis struct [<$data Def>] {
|
||||
$(
|
||||
pub [<$variant:snake:lower>]: [<$data Def Variant $variant>],
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
::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 = ::paste::paste! { [<$data Def>] };
|
||||
|
||||
fn filter_ref(&mut self, def: &Self::Definition) {
|
||||
match self {
|
||||
$(
|
||||
Self::$variant { $( ref mut $field ),+ } => {
|
||||
let def = ::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 {
|
||||
macro_rules! query_def_struct {
|
||||
(
|
||||
$(
|
||||
$(#[$meta:meta])
|
||||
*
|
||||
$vis:vis $data:ident(
|
||||
$vis:vis $data:ident$((
|
||||
$(#[$def_meta:meta])
|
||||
*
|
||||
$def:ident
|
||||
) {
|
||||
+
|
||||
))? {
|
||||
$(
|
||||
$(#[$field_meta:meta])
|
||||
*
|
||||
|
@ -159,15 +253,14 @@ macro_rules! query_def {
|
|||
)
|
||||
*
|
||||
) => {
|
||||
$crate::query_def_internal!(@
|
||||
$crate::query_def_internal_struct!(@
|
||||
$(
|
||||
$(#[$meta])
|
||||
*
|
||||
$vis $data(
|
||||
$vis $data$((
|
||||
$(#[$def_meta])
|
||||
*
|
||||
$def
|
||||
) {
|
||||
+
|
||||
))? {
|
||||
$(
|
||||
$(#[$field_meta])
|
||||
*
|
||||
|
@ -180,19 +273,77 @@ macro_rules! query_def {
|
|||
};
|
||||
}
|
||||
|
||||
/// Defines a dynamic query structure.
|
||||
#[cfg(feature = "serde")]
|
||||
/// Defines a dynamic enumerated query structure.
|
||||
#[cfg(not(feature = "serde"))]
|
||||
#[macro_export]
|
||||
macro_rules! query_def {
|
||||
macro_rules! query_def_enum {
|
||||
(
|
||||
$(
|
||||
$(#[$meta:meta])
|
||||
*
|
||||
$vis:vis $data:ident(
|
||||
$vis:vis $data:ident$((
|
||||
$(#[$def_meta:meta])
|
||||
*
|
||||
$def:ident
|
||||
) {
|
||||
+
|
||||
))? {
|
||||
$(
|
||||
$(#[$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])
|
||||
*
|
||||
|
@ -202,7 +353,7 @@ macro_rules! query_def {
|
|||
)
|
||||
*
|
||||
) => {
|
||||
$crate::query_def_internal!(@
|
||||
$crate::query_def_internal_struct!(@
|
||||
$(
|
||||
#[derive(Serialize, Deserialize)]
|
||||
$(#[$meta])
|
||||
|
@ -210,9 +361,10 @@ macro_rules! query_def {
|
|||
$vis $data(
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
$(
|
||||
$(#[$def_meta])
|
||||
*
|
||||
$def
|
||||
+
|
||||
)?
|
||||
) {
|
||||
$(
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
@ -226,3 +378,72 @@ macro_rules! query_def {
|
|||
);
|
||||
};
|
||||
}
|
||||
|
||||
/// 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)+),
|
||||
)+
|
||||
}
|
||||
),+
|
||||
}
|
||||
)
|
||||
*
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue