use std::sync::Arc;
use indexmap::IndexMap;
use crate::{column::flags::ColumnFlag, traits::column_like::ColumnLike};
pub trait ColumnCollectionExt {
fn only(&self, flag: ColumnFlag) -> Arc<IndexMap<String, Arc<dyn ColumnLike>>>;
fn exclude(&self, flag: ColumnFlag) -> Arc<IndexMap<String, Arc<dyn ColumnLike>>>;
}
impl ColumnCollectionExt for Arc<IndexMap<String, Arc<dyn ColumnLike>>> {
fn only(&self, flag: ColumnFlag) -> Arc<IndexMap<String, Arc<dyn ColumnLike>>> {
let filtered: IndexMap<String, Arc<dyn ColumnLike>> = self
.iter()
.filter(|(_, col)| col.flags().contains(&flag))
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
Arc::new(filtered)
}
fn exclude(&self, flag: ColumnFlag) -> Arc<IndexMap<String, Arc<dyn ColumnLike>>> {
let filtered: IndexMap<String, Arc<dyn ColumnLike>> = self
.iter()
.filter(|(_, col)| !col.flags().contains(&flag))
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
Arc::new(filtered)
}
}
#[cfg(test)]
mod tests {
use crate::column::core::Column;
use super::*;
#[test]
fn test_only_filter() {
let mut columns: IndexMap<String, Arc<dyn ColumnLike>> = IndexMap::new();
columns.insert(
"id".to_string(),
Arc::new(Column::new("id").with_flags(&[ColumnFlag::Mandatory])),
);
columns.insert(
"name".to_string(),
Arc::new(Column::new("name").with_flags(&[ColumnFlag::Mandatory])),
);
columns.insert(
"description".to_string(),
Arc::new(Column::new("description")),
);
let arc_columns = Arc::new(columns);
let mandatory = arc_columns.only(ColumnFlag::Mandatory);
assert_eq!(mandatory.len(), 2);
assert!(mandatory.contains_key("id"));
assert!(mandatory.contains_key("name"));
assert!(!mandatory.contains_key("description"));
}
#[test]
fn test_exclude_filter() {
let mut columns: IndexMap<String, Arc<dyn ColumnLike>> = IndexMap::new();
columns.insert(
"id".to_string(),
Arc::new(Column::new("id").with_flags(&[ColumnFlag::Hidden])),
);
columns.insert("name".to_string(), Arc::new(Column::new("name")));
columns.insert(
"password".to_string(),
Arc::new(Column::new("password").with_flags(&[ColumnFlag::Hidden])),
);
let arc_columns = Arc::new(columns);
let visible = arc_columns.exclude(ColumnFlag::Hidden);
assert_eq!(visible.len(), 1);
assert!(visible.contains_key("name"));
assert!(!visible.contains_key("id"));
assert!(!visible.contains_key("password"));
}
#[test]
fn test_chaining_filters() {
let mut columns: IndexMap<String, Arc<dyn ColumnLike>> = IndexMap::new();
columns.insert(
"id".to_string(),
Arc::new(Column::new("id").with_flags(&[ColumnFlag::Mandatory])),
);
columns.insert(
"name".to_string(),
Arc::new(Column::new("name").with_flags(&[ColumnFlag::Mandatory, ColumnFlag::Hidden])),
);
columns.insert("email".to_string(), Arc::new(Column::new("email")));
let arc_columns = Arc::new(columns);
let visible_mandatory = arc_columns
.exclude(ColumnFlag::Hidden)
.only(ColumnFlag::Mandatory);
assert_eq!(visible_mandatory.len(), 1);
assert!(visible_mandatory.contains_key("id"));
assert!(!visible_mandatory.contains_key("name")); assert!(!visible_mandatory.contains_key("email")); }
}