Enum support, use paste to generate definition struct names

This commit is contained in:
Michael Pfaff 2022-05-27 18:07:00 -04:00
parent bde3ce5cce
commit 4c6aadf634
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
2 changed files with 290 additions and 39 deletions

View File

@ -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,
})
}
}

View File

@ -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)+),
)+
}
),+
}
)
*
);
};
}