I have this big rust struct (DictWordMetadata), with more structs contained inside it. I have to check the value of a specific field in this struct or the structs contained inside it agains the value of a filter. This filter comes in JSON form, but I currently deserialize it to the same type (DictWordMetadata).
To give an example to make the problem clearer, the filter can come as the following JSON:
"metadata_condition": {
"stress": "Oxitona"
},
The struct I was referring to has the following format:
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Hash)]
pub struct DictWordMetadata {
pub noun: Option<NounData>,
pub pronoun: Option<PronounData>,
pub verb: Option<VerbData>,
pub adjective: Option<AdjectiveData>,
pub adverb: Option<AdverbData>,
pub conjunction: Option<ConjunctionData>,
pub swear: Option<bool>,
/// The dialects this word belongs to.
/// If no dialects are defined, it can be assumed that the word is
/// valid in all dialects of English.
#[serde(default = "default_default")]
pub dialects: DialectFlags,
/// Orthographic information: letter case, spaces, hyphens, etc.
#[serde(default = "OrthFlags::empty")]
pub orth_info: OrthFlags,
/// Whether the word is a [determiner](https://en.wikipedia.org/wiki/English_determiners).
pub determiner: Option<DeterminerData>,
/// Whether the word is a [preposition](https://www.merriam-webster.com/dictionary/preposition).
#[serde(default = "default_false")]
pub preposition: bool,
/// Whether the word is considered especially common.
#[serde(default = "default_false")]
pub common: bool,
#[serde(default = "default_none")]
pub derived_from: Option<WordId>,
/// Generated by a chunker
pub np_member: Option<bool>,
/// Generated by a POS tagger
pub pos_tag: Option<UPOS>,
// The two under here are only used in the Portuguese grammar
/// In which of the last three syllables of the word is the stress
pub stress: Option<Stress>,
/// Words in portuguese are split between masculine and feminine
pub gender: Option<Gender>,
}
So I'd have to check if the stress on my initial object (not the filter) has the same value of the value in the filter, and if so I return true. But I have to do this for every possible value, including recursively. I imagine the solution has something to do with macros, but just with declarative macros I couldn't get anywhere, and proc macros might me overkill (all the trouble of setting up a separate crate just for a minor function). Any ideas on how to solve this?
I also made this attempt, but as you can probably notice it doesn't have the recursivity I wanted nor does it work well to begin with, because it compares the whole object after extracting it from the Option, instead of comparing only the stuff that was set
macro_rules! check_metadata_condition {
( $obj:expr, $cond:expr, $($field:ident),+ $(,)? ) => {{
$(
if let (Some(equal), Some(cond_val)) = (&$obj.$field, &$cond.$field) {
if obj_val != cond_val {
return false;
}
}
)+
true
}};
}
To be clear, I'm not asking for anyone to implement this, although some examples would be great. Just asking for some guidance of how to approach this problem in the first place, maybe changing the way I deserialize the filter to begin with or something like this. Thank you.