psyche_utils/bucket_strainer/
layer.rs

1use crate::bucket_strainer::Bucket;
2use std::mem;
3
4/// Bucket strainer layer that contains buckets.
5#[derive(Clone)]
6pub struct Layer<T>
7where
8    T: Clone,
9{
10    buckets: Vec<Bucket<T>>,
11}
12
13impl<T> Layer<T>
14where
15    T: Clone,
16{
17    pub fn new(buckets: Vec<Bucket<T>>) -> Self {
18        Self { buckets }
19    }
20
21    pub fn buckets(&self) -> &[Bucket<T>] {
22        &self.buckets
23    }
24
25    pub fn replace_buckets(&mut self, buckets: Vec<Bucket<T>>) -> Vec<Bucket<T>> {
26        mem::replace(&mut self.buckets, buckets)
27    }
28
29    pub fn bucket(&self, id: &str) -> Option<&Bucket<T>> {
30        self.buckets.iter().find(|bucket| bucket.id() == id)
31    }
32
33    pub(crate) fn clear_buckets(&mut self) {
34        for bucket in &mut self.buckets {
35            bucket.clear();
36        }
37    }
38
39    pub(crate) fn process(&mut self, items: Vec<T>) -> Vec<T> {
40        items
41            .into_iter()
42            .filter(|item| {
43                if let Some(bucket) = self.select_bucket(&item) {
44                    bucket.insert(item.clone());
45                    false
46                } else {
47                    true
48                }
49            })
50            .collect()
51    }
52
53    fn select_bucket(&mut self, item: &T) -> Option<&mut Bucket<T>> {
54        self.buckets
55            .iter_mut()
56            .filter_map(|bucket| bucket.score(item).map(|score| (bucket, score)))
57            .max_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
58            .map(|(bucket, _)| bucket)
59    }
60}