hydrant/
filter.rs

1use serde::{Deserialize, Serialize};
2use smol_str::SmolStr;
3use std::sync::Arc;
4
5pub(crate) type FilterHandle = Arc<arc_swap::ArcSwap<FilterConfig>>;
6
7pub(crate) fn new_handle(config: FilterConfig) -> FilterHandle {
8    Arc::new(arc_swap::ArcSwap::new(Arc::new(config)))
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13pub enum FilterMode {
14    Filter = 0,
15    Full = 2,
16}
17
18#[derive(Debug, Clone, Serialize)]
19pub(crate) struct FilterConfig {
20    pub mode: FilterMode,
21    pub signals: Vec<SmolStr>,
22    pub collections: Vec<SmolStr>,
23}
24
25impl FilterConfig {
26    pub fn new(mode: FilterMode) -> Self {
27        Self {
28            mode,
29            signals: Vec::new(),
30            collections: Vec::new(),
31        }
32    }
33}
34
35#[cfg(feature = "indexer")]
36mod indexer {
37    use super::*;
38
39    impl FilterConfig {
40        pub fn matches_collection(&self, collection: &str) -> bool {
41            if self.collections.is_empty() {
42                return true;
43            }
44            self.collections.iter().any(|p| nsid_matches(p, collection))
45        }
46
47        pub fn matches_signal(&self, collection: &str) -> bool {
48            self.signals.iter().any(|p| nsid_matches(p, collection))
49        }
50
51        pub fn check_signals(&self) -> bool {
52            self.mode == FilterMode::Filter && !self.signals.is_empty()
53        }
54    }
55
56    fn nsid_matches(pattern: &str, col: &str) -> bool {
57        pattern
58            .strip_suffix(".*")
59            .map(|prefix| col == prefix || col.starts_with(prefix))
60            .unwrap_or_else(|| col == pattern)
61    }
62}