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);
|
fn filter_ref(&mut self, def: &Self::Definition);
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn filter(mut self, def: &Self::Definition) -> Self
|
fn filter(mut self, def: &Self::Definition) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
@ -19,10 +20,13 @@ mod macros;
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::DynamicQuery;
|
||||||
|
|
||||||
// just tests that the macro compiles
|
// just tests that the macro compiles
|
||||||
crate::query_def! {
|
crate::query_def_struct! {
|
||||||
/// Foo doc.
|
/// Foo doc.
|
||||||
Foo(FooDef) {
|
#[derive(PartialEq)]
|
||||||
|
Foo {
|
||||||
/// Field doc.
|
/// Field doc.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
bar: (Bar),
|
bar: (Bar),
|
||||||
|
@ -32,21 +36,47 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bar doc.
|
/// Bar doc.
|
||||||
Bar(BarDef) {
|
#[derive(PartialEq)]
|
||||||
|
Bar {
|
||||||
baz_inner: (bool),
|
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
|
// make sure A. serde is working and B. we get expected structure
|
||||||
#[test]
|
#[test]
|
||||||
fn test_json() {
|
fn test_json() {
|
||||||
assert_eq!(serde_json::to_string(&Foo {
|
let x = Foo {
|
||||||
bar: Some(Bar {
|
bar: Some(Bar {
|
||||||
baz_inner: Some(true),
|
baz_inner: Some(true),
|
||||||
}),
|
}),
|
||||||
baz: Some(false),
|
baz: Some(false),
|
||||||
bars: Some(vec![]),
|
bars: Some(vec![]),
|
||||||
bars_by_bazs: Some(std::collections::HashMap::new()),
|
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
|
$type
|
||||||
};
|
};
|
||||||
(@ 'vec ($type:ty)) => {
|
(@ 'vec ($type:ty)) => {
|
||||||
Vec<$type>
|
::std::vec::Vec<$type>
|
||||||
};
|
};
|
||||||
(@ 'map ($key:ty, $value:ty)) => {
|
(@ 'map ($key:ty, $value:ty)) => {
|
||||||
::std::collections::HashMap<$key, $value>
|
::std::collections::HashMap<$key, $value>
|
||||||
|
@ -80,16 +80,15 @@ macro_rules! query_def_filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_def_internal {
|
macro_rules! query_def_internal_struct {
|
||||||
(@
|
(@
|
||||||
$(
|
$(
|
||||||
$(#[$meta:meta])
|
$(#[$meta:meta])
|
||||||
*
|
*
|
||||||
$vis:vis $data:ident(
|
$vis:vis $data:ident$((
|
||||||
$(#[$def_meta:meta])
|
$(#[$def_meta:meta])
|
||||||
*
|
+
|
||||||
$def:ident
|
))? {
|
||||||
) {
|
|
||||||
$(
|
$(
|
||||||
$(#[$field_meta:meta])
|
$(#[$field_meta:meta])
|
||||||
*
|
*
|
||||||
|
@ -111,17 +110,18 @@ macro_rules! query_def_internal {
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
::paste::paste! {
|
||||||
$(#[$def_meta])
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
*
|
$( $( #[$def_meta] )+ )?
|
||||||
$vis struct $def {
|
$vis struct [<$data Def>] {
|
||||||
$(
|
$(
|
||||||
pub $field: $crate::query_def_field!(@ $($qualifier)? ($($type)+)),
|
pub $field: $crate::query_def_field!(@ $($qualifier)? ($($type)+)),
|
||||||
)+
|
)+
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::DynamicQuery for $data {
|
impl $crate::DynamicQuery for $data {
|
||||||
type Definition = $def;
|
type Definition = ::paste::paste! { [<$data Def>] };
|
||||||
|
|
||||||
fn filter_ref(&mut self, def: &Self::Definition) {
|
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.
|
/// Defines a dynamic query structure.
|
||||||
#[cfg(not(feature = "serde"))]
|
#[cfg(not(feature = "serde"))]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_def {
|
macro_rules! query_def_struct {
|
||||||
(
|
(
|
||||||
$(
|
$(
|
||||||
$(#[$meta:meta])
|
$(#[$meta:meta])
|
||||||
*
|
*
|
||||||
$vis:vis $data:ident(
|
$vis:vis $data:ident$((
|
||||||
$(#[$def_meta:meta])
|
$(#[$def_meta:meta])
|
||||||
*
|
+
|
||||||
$def:ident
|
))? {
|
||||||
) {
|
|
||||||
$(
|
$(
|
||||||
$(#[$field_meta:meta])
|
$(#[$field_meta:meta])
|
||||||
*
|
*
|
||||||
|
@ -159,15 +253,14 @@ macro_rules! query_def {
|
||||||
)
|
)
|
||||||
*
|
*
|
||||||
) => {
|
) => {
|
||||||
$crate::query_def_internal!(@
|
$crate::query_def_internal_struct!(@
|
||||||
$(
|
$(
|
||||||
$(#[$meta])
|
$(#[$meta])
|
||||||
*
|
*
|
||||||
$vis $data(
|
$vis $data$((
|
||||||
$(#[$def_meta])
|
$(#[$def_meta])
|
||||||
*
|
+
|
||||||
$def
|
))? {
|
||||||
) {
|
|
||||||
$(
|
$(
|
||||||
$(#[$field_meta])
|
$(#[$field_meta])
|
||||||
*
|
*
|
||||||
|
@ -180,19 +273,77 @@ macro_rules! query_def {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines a dynamic query structure.
|
/// Defines a dynamic enumerated query structure.
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(not(feature = "serde"))]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_def {
|
macro_rules! query_def_enum {
|
||||||
(
|
(
|
||||||
$(
|
$(
|
||||||
$(#[$meta:meta])
|
$(#[$meta:meta])
|
||||||
*
|
*
|
||||||
$vis:vis $data:ident(
|
$vis:vis $data:ident$((
|
||||||
$(#[$def_meta:meta])
|
$(#[$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])
|
$(#[$field_meta:meta])
|
||||||
*
|
*
|
||||||
|
@ -202,7 +353,7 @@ macro_rules! query_def {
|
||||||
)
|
)
|
||||||
*
|
*
|
||||||
) => {
|
) => {
|
||||||
$crate::query_def_internal!(@
|
$crate::query_def_internal_struct!(@
|
||||||
$(
|
$(
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
$(#[$meta])
|
$(#[$meta])
|
||||||
|
@ -210,9 +361,10 @@ macro_rules! query_def {
|
||||||
$vis $data(
|
$vis $data(
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
$(
|
||||||
$(#[$def_meta])
|
$(#[$def_meta])
|
||||||
*
|
+
|
||||||
$def
|
)?
|
||||||
) {
|
) {
|
||||||
$(
|
$(
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[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