This commit is contained in:
Michael Pfaff 2022-05-30 07:40:22 -04:00
parent df882cb64c
commit 5ce0f242f6
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
2 changed files with 33 additions and 103 deletions

View File

@ -1,8 +1,8 @@
//! A crate providing a (mostly) straighforward syntax for defining dynamic structures for //! A crate providing a (mostly) straighforward syntax for defining dynamic structures for
//! efficient querying. //! efficient querying.
//! //!
//! # Features //! # Features
//! //!
//! - Filter a struct or enum according to a query definition. //! - Filter a struct or enum according to a query definition.
//! - Inspect definitions manually to avoid unnecessary computations before filtering. //! - Inspect definitions manually to avoid unnecessary computations before filtering.
//! //!
@ -13,7 +13,7 @@
//! this may be supported for all aspects in the future. //! this may be supported for all aspects in the future.
//! //!
//! # Structs //! # Structs
//! //!
//! Only struct structs (yes, that is what they're [called](https://doc.rust-lang.org/reference/items/structs.html)), //! Only struct structs (yes, that is what they're [called](https://doc.rust-lang.org/reference/items/structs.html)),
//! are supported. Struct structs with no fields are also not supported. //! are supported. Struct structs with no fields are also not supported.
//! //!
@ -48,9 +48,9 @@
//! ``` //! ```
//! //!
//! # Enums //! # Enums
//! //!
//! Fieldless and struct enums are supported, but struct enums with no fields are not. //! Fieldless and struct enums are supported, but struct enums with no fields are not.
//! //!
//! This fails: //! This fails:
//! ```compile_fail //! ```compile_fail
//! # #[macro_use] extern crate ql; //! # #[macro_use] extern crate ql;
@ -94,11 +94,12 @@ pub trait DynamicQuery {
/// A type defining the fields to include in the filtered structure. /// A type defining the fields to include in the filtered structure.
type Definition; type Definition;
/// Filters the fields of this structure in place. /// Filters the fields of this structure in place according to the `def`.
fn filter_ref(&mut self, def: &Self::Definition); fn filter_ref(&mut self, def: &Self::Definition);
/// Filters the fields of this structure in place. This method takes ownership of the /// Filters the fields of this structure in place according to the `def`.
/// structure, making it more suitable for pipelines. /// This method takes ownership of the structure, making it more suitable
/// for pipelines.
#[inline(always)] #[inline(always)]
fn filter(mut self, def: &Self::Definition) -> Self fn filter(mut self, def: &Self::Definition) -> Self
where where
@ -177,18 +178,24 @@ mod tests {
bars: Some(vec![]), bars: Some(vec![]),
bars_by_bazs: Some(std::collections::HashMap::new()), bars_by_bazs: Some(std::collections::HashMap::new()),
}; };
assert_eq!(serde_json::to_string(&x).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 { assert_eq!(
bar: false, x.clone().filter(&FooDef {
baz: true, bar: false,
bars: Some(BarDef::default()), baz: true,
bars_by_bazs: None, bars: Some(BarDef::default()),
}), Foo { bars_by_bazs: None,
bar: None, }),
baz: Some(false), Foo {
bars: Some(vec![]), bar: None,
bars_by_bazs: None, baz: Some(false),
}) bars: Some(vec![]),
bars_by_bazs: None,
}
)
} }
} }

View File

@ -95,8 +95,6 @@ macro_rules! query_def_internal_struct {
$( #[$field_meta:meta] )* $( #[$field_meta:meta] )*
$field:ident: $( $qualifier:lifetime )? ($( $type:tt )+) $field:ident: $( $qualifier:lifetime )? ($( $type:tt )+)
),+ ),+
$(,)?
} }
) => { ) => {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -146,7 +144,7 @@ macro_rules! query_def_internal_enum_variant_def {
$vis:vis $name:ident { $vis:vis $name:ident {
$( $field:ident$(( $( $field:ident$((
$( #[$variant_def_field_meta:meta] )+ $( #[$variant_def_field_meta:meta] )+
))?: $($qualifier:lifetime)? ($($type:tt)+) ),+ ))?: $( $qualifier:lifetime )? ($( $type:tt )+) ),+
} }
) => { ) => {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
@ -179,11 +177,8 @@ macro_rules! query_def_internal_enum {
$( #[$variant_def_field_meta:meta] )+ $( #[$variant_def_field_meta:meta] )+
))?: $( $qualifier:lifetime )? ($( $type:tt )+) ))?: $( $qualifier:lifetime )? ($( $type:tt )+)
),+ ),+
$(,)?
})? })?
),+ ),+
$(,)?
} }
) => { ) => {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -272,8 +267,8 @@ macro_rules! query_def_0 {
))? { ))? {
$( $(
$( #[$field_meta] )* $( #[$field_meta] )*
$field: $( $qualifier )? ($( $type )+), $field: $( $qualifier )? ($( $type )+)
)+ ),+
} }
} }
}; };
@ -394,8 +389,8 @@ macro_rules! query_def_0 {
$( #[$field_meta] )* $( #[$field_meta] )*
$field( $field(
#[serde(default)] #[serde(default)]
): $( $qualifier )? ($( $type )+), ): $( $qualifier )? ($( $type )+)
)+ ),+
})? })?
),+ ),+
} }
@ -405,79 +400,7 @@ macro_rules! query_def_0 {
/// Defines a dynamic query structure. /// Defines a dynamic query structure.
/// ///
/// # Structs /// See the crate documentation for details.
///
/// Only struct structs (yes, that is what they're [called](https://doc.rust-lang.org/reference/items/structs.html)), are supported. Struct structs with no fields are also not supported.
///
/// This fails:
/// ```compile_fail
/// # #[macro_use] extern crate ql;
/// #
/// query_def! {
/// struct Foo {
/// }
/// }
/// #
/// # fn main() {
/// # }
/// ```
///
/// This works:
/// ```
/// # #[macro_use] extern crate ql;
/// #
/// query_def! {
/// struct Foo {
/// a: (bool),
/// b: (usize),
/// c: (String),
/// d: (Vec<String>),
/// }
/// }
/// #
/// # fn main() {
/// # }
/// ```
///
/// # Enums
///
/// Fieldless and struct enums are supported, but struct enums with no fields are not.
///
/// This fails:
/// ```compile_fail
/// # #[macro_use] extern crate ql;
/// #
/// query_def! {
/// enum Foo {
/// A { }
/// }
/// }
/// #
/// # fn main() {
/// # }
/// ```
///
/// This works:
/// ```
/// # #[macro_use] extern crate ql;
/// #
/// query_def! {
/// enum Foo {
/// A
/// }
/// }
/// #
/// # fn main() {
/// # }
/// ```
///
/// Incorrect syntax in the macro invocation can lead to very confusing errors.
///
/// For example, the incorrect enum syntax shown earlier will fail with this message:
///
/// ```text
/// error: no rules expected the token `struct`
/// ```
#[macro_export] #[macro_export]
macro_rules! query_def { macro_rules! query_def {
($( ($(