Skip to content

Commit 58754b3

Browse files
committed
[function-grep] working on filter merging
1 parent 659aa89 commit 58754b3

File tree

1 file changed

+68
-15
lines changed

1 file changed

+68
-15
lines changed

function-grep/src/filter.rs

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ impl From<Language> for SupportedLanguages {
200200
Self::Single(value.0)
201201
}
202202
}
203+
impl fmt::Display for Language {
204+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205+
write!(f, "{}", self.0)
206+
}
207+
}
203208
// impl Language for
204209
// TODO: rework macro to work with the new language per filter system
205210
macro_rules! default_filters {
@@ -213,6 +218,7 @@ pub struct Many<T: Info<Supported = Language>> {
213218
pub filters: HashMap<String, T>,
214219
}
215220

221+
// TODO: merge with HasFilterInformation
216222
pub trait Info {
217223
type Supported;
218224
fn filter_name(&self) -> String;
@@ -242,10 +248,10 @@ impl<A: Info<Supported = All>, M: Info<Supported = Language>> SingleOrMany<A, M>
242248
#[must_use]
243249
pub fn supports(&self) -> SupportedLanguages {
244250
match self {
245-
// Self::Single(s) => SupportedLanguages::Single(s.)
246251
Self::All(_) => SupportedLanguages::All,
247252
Self::Many(many) => SupportedLanguages::Many(many.filters.keys().cloned().collect()),
248-
SingleOrMany::Single(_) => todo!(),
253+
// TODO: make Info carry not just the supported type but also a value for it
254+
Self::Single(_s) => todo!(),
249255
}
250256
}
251257
}
@@ -255,6 +261,7 @@ impl<A: Info<Supported = All>, M: Info<Supported = Language>> Display for Single
255261
}
256262
}
257263
impl<'a> FilterType<'a> {
264+
#[must_use]
258265
pub fn specific(&self, s: &str) -> Option<Self> {
259266
match self {
260267
Self::All(_) | Self::Single(_) => None,
@@ -351,19 +358,43 @@ impl Filters<'static> {
351358

352359
impl<'a> Filters<'a> {
353360
pub fn add_filter(&mut self, filter: impl Into<FilterType<'a>>) -> Result<(), String> {
354-
let filter = filter.into();
361+
let filter: FilterType<'a> = filter.into();
355362
let name = filter.filter_name();
356363
if let Some(filters) = self.filters.get_mut(&name) {
357364
match filters {
358-
SingleOrMany::All(_) => Err("cannot add to an all filter".to_string()),
359-
SingleOrMany::Many(Many { filters, .. }) => merge_filters(filters, filter),
360-
SingleOrMany::Single(s) => {
361-
*filters = SingleOrMany::Many(Many {
362-
name: "".to_string(),
363-
filters: HashMap::from([(s.filter_name(), *s)]),
364-
});
365-
Ok(())
365+
SingleOrMany::All(_) => Err("cannot add with or to an all filter".to_string()),
366+
_ if matches!(filter, SingleOrMany::All(_)) => {
367+
Err("cannot add with or to an all filter".to_string())
366368
}
369+
SingleOrMany::Many(filter1) => match filter {
370+
SingleOrMany::All(_) => unreachable!(),
371+
SingleOrMany::Many(filter2) => try_extend_filter(filter1, filter2),
372+
SingleOrMany::Single(filter2) => try_add_filter(filter1, filter2),
373+
},
374+
SingleOrMany::Single(filter1) => match filter {
375+
SingleOrMany::All(_) => unreachable!(),
376+
SingleOrMany::Many(mut filter2) => {
377+
try_add_filter(&mut filter2, *filter1)?;
378+
*filters = SingleOrMany::Many(filter2);
379+
Ok(())
380+
}
381+
SingleOrMany::Single(filter2) if filter1.supports() == filter2.supports() => {
382+
Err(format!(
383+
"cannot add duplicate filter {name} for {}",
384+
filter1.supports()
385+
))
386+
}
387+
SingleOrMany::Single(filter2) => {
388+
*filters = SingleOrMany::Many(Many {
389+
name,
390+
filters: HashMap::from([
391+
(filter1.supports().0, *filter1),
392+
(filter2.supports().0, filter2),
393+
]),
394+
});
395+
Ok(())
396+
}
397+
},
367398
}
368399
} else {
369400
self.filters.insert(name, filter);
@@ -376,9 +407,31 @@ impl<'a> Filters<'a> {
376407
}
377408
}
378409

379-
fn merge_filters<'a>(
380-
hash_map: &mut HashMap<String, &'a dyn Filter<Supports = Language>>,
381-
filter: FilterType<'a>,
410+
fn try_add_filter<'a>(
411+
filters: &mut Many<&'a (dyn Filter<Supports = Language>)>,
412+
filter: &'a (dyn Filter<Supports = Language>),
413+
) -> Result<(), String> {
414+
let mut status = Ok(());
415+
filters
416+
.filters
417+
.entry(filter.supports().0)
418+
.and_modify(|_| {
419+
status = Err(format!(
420+
"cannot add duplicate filter {} for {}",
421+
filter.filter_name(),
422+
filter.supports()
423+
));
424+
})
425+
.or_insert(filter);
426+
status
427+
}
428+
429+
fn try_extend_filter<'a>(
430+
filters: &mut Many<&'a (dyn Filter<Supports = Language>)>,
431+
new_filters: Many<&'a (dyn Filter<Supports = Language>)>,
382432
) -> Result<(), String> {
383-
todo!()
433+
new_filters
434+
.filters
435+
.into_values()
436+
.try_for_each(|filter| try_add_filter(filters, filter))
384437
}

0 commit comments

Comments
 (0)