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}