use nodedb_types::PayloadAtom;
use nodedb_types::filter::MetadataFilter;
use crate::error::LiteError;
pub(crate) fn payload_atoms_to_metadata(
atoms: &[PayloadAtom],
) -> Result<Option<MetadataFilter>, LiteError> {
let mut parts = Vec::with_capacity(atoms.len());
for atom in atoms {
parts.push(atom_to_metadata(atom)?);
}
Ok(match parts.len() {
0 => None,
1 => parts.pop(),
_ => Some(MetadataFilter::And(parts)),
})
}
fn atom_to_metadata(atom: &PayloadAtom) -> Result<MetadataFilter, LiteError> {
match atom {
PayloadAtom::Eq(field, value) => Ok(MetadataFilter::Eq {
field: field.clone(),
value: value.clone(),
}),
PayloadAtom::In(field, values) => Ok(MetadataFilter::In {
field: field.clone(),
values: values.clone(),
}),
PayloadAtom::Range {
field,
low,
low_inclusive,
high,
high_inclusive,
} => {
let mut parts = Vec::with_capacity(2);
if let Some(lo) = low {
parts.push(if *low_inclusive {
MetadataFilter::Gte {
field: field.clone(),
value: lo.clone(),
}
} else {
MetadataFilter::Gt {
field: field.clone(),
value: lo.clone(),
}
});
}
if let Some(hi) = high {
parts.push(if *high_inclusive {
MetadataFilter::Lte {
field: field.clone(),
value: hi.clone(),
}
} else {
MetadataFilter::Lt {
field: field.clone(),
value: hi.clone(),
}
});
}
match parts.len() {
0 => Err(LiteError::BadRequest {
detail: format!("payload range on '{field}' has no bounds"),
}),
1 => Ok(parts.remove(0)),
_ => Ok(MetadataFilter::And(parts)),
}
}
other => Err(LiteError::BadRequest {
detail: format!("payload filter atom not supported by this build: {other:?}"),
}),
}
}
pub(crate) fn and_metadata(
a: Option<MetadataFilter>,
b: Option<MetadataFilter>,
) -> Option<MetadataFilter> {
match (a, b) {
(None, None) => None,
(Some(f), None) | (None, Some(f)) => Some(f),
(Some(a), Some(b)) => Some(MetadataFilter::And(vec![a, b])),
}
}