use crate::{Archive, TableSelector, TocEntry};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
enum NamespaceCriterion {
#[default]
Any,
Absent,
Exact(Vec<u8>),
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct MetadataFilter {
namespace: NamespaceCriterion,
object_type: Option<Vec<u8>>,
name: Option<Vec<u8>>,
}
impl MetadataFilter {
pub fn new() -> Self {
Self::default()
}
pub fn with_schema(mut self, schema: impl AsRef<[u8]>) -> Self {
self.namespace = NamespaceCriterion::Exact(schema.as_ref().to_vec());
self
}
pub fn with_absent_schema(mut self) -> Self {
self.namespace = NamespaceCriterion::Absent;
self
}
pub fn with_object_type(mut self, object_type: impl AsRef<[u8]>) -> Self {
self.object_type = Some(object_type.as_ref().to_vec());
self
}
pub fn with_name(mut self, name: impl AsRef<[u8]>) -> Self {
self.name = Some(name.as_ref().to_vec());
self
}
pub fn matches(&self, entry: &TocEntry) -> bool {
let namespace_matches = match &self.namespace {
NamespaceCriterion::Any => true,
NamespaceCriterion::Absent => entry.namespace_bytes().is_none(),
NamespaceCriterion::Exact(expected) => {
entry.namespace_bytes() == Some(expected.as_slice())
}
};
let object_type_matches = match &self.object_type {
Some(expected) => entry.description_bytes() == expected.as_slice(),
None => true,
};
let name_matches = match &self.name {
Some(expected) => entry.name_bytes() == expected.as_slice(),
None => true,
};
namespace_matches && object_type_matches && name_matches
}
}
#[derive(Debug, Clone, Copy)]
pub struct MetadataMatch<'a> {
entry: &'a TocEntry,
}
impl<'a> MetadataMatch<'a> {
pub const fn entry(&self) -> &'a TocEntry {
self.entry
}
pub fn table_selector(&self) -> Option<TableSelector> {
if !self.entry.is_table() {
return None;
}
let schema = self.entry.namespace_bytes()?;
Some(TableSelector::new(schema, self.entry.name_bytes()))
}
}
impl<R> Archive<R> {
pub fn filter_metadata<'a>(&'a self, filter: &MetadataFilter) -> Vec<MetadataMatch<'a>> {
self.entries()
.iter()
.filter(|entry| filter.matches(entry))
.map(|entry| MetadataMatch { entry })
.collect()
}
}