1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use crate::rpc::eth::FilterID;
use crate::rpc::Arc;
use ahash::AHashMap as HashMap;
use anyhow::anyhow;
use anyhow::Result;
use parking_lot::RwLock;
use std::any::Any;

/// This trait should be implemented by any filter that needs to be identified
/// and managed. It provide methods to retrieve the unique identifier for
/// the filter.
pub trait Filter: Send + Sync + std::fmt::Debug {
    fn id(&self) -> &FilterID;
    fn as_any(&self) -> &dyn Any;
}

/// The `FilterStore` trait provides the necessary interface for storing and managing filters.
pub trait FilterStore: Send + Sync {
    fn add(&self, filter: Arc<dyn Filter>) -> Result<()>;
    fn get(&self, id: &FilterID) -> Result<Arc<dyn Filter>>;
    fn remove(&self, id: &FilterID) -> Option<Arc<dyn Filter>>;
}

#[derive(Debug)]
pub struct MemFilterStore {
    max: usize,
    filters: RwLock<HashMap<FilterID, Arc<dyn Filter>>>,
}

impl MemFilterStore {
    pub fn new(max_filters: usize) -> Arc<Self> {
        Arc::new(Self {
            max: max_filters,
            filters: RwLock::new(HashMap::new()),
        })
    }
}

impl FilterStore for MemFilterStore {
    fn add(&self, filter: Arc<dyn Filter>) -> Result<()> {
        let mut filters = self.filters.write();

        if filters.len() == self.max {
            return Err(anyhow::Error::msg("Maximum number of filters registered"));
        }
        if filters.contains_key(filter.id()) {
            return Err(anyhow::Error::msg("Filter already registered"));
        }
        filters.insert(filter.id().clone(), filter);
        Ok(())
    }

    fn get(&self, id: &FilterID) -> Result<Arc<dyn Filter>> {
        let filters = self.filters.read();
        filters
            .get(id)
            .cloned()
            .ok_or_else(|| anyhow!("Filter with the given ID not found"))
    }

    fn remove(&self, id: &FilterID) -> Option<Arc<dyn Filter>> {
        let mut filters = self.filters.write();
        filters.remove(id)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::rpc::eth::FilterID;
    use std::sync::Arc;

    #[derive(Debug)]
    struct TestFilter {
        id: FilterID,
    }

    impl Filter for TestFilter {
        fn id(&self) -> &FilterID {
            &self.id
        }

        fn as_any(&self) -> &dyn Any {
            self
        }
    }

    #[test]
    fn test_add_filter() {
        let store = MemFilterStore::new(2);

        let filter1 = Arc::new(TestFilter {
            id: FilterID::new().unwrap(),
        });
        let filter2 = Arc::new(TestFilter {
            id: FilterID::new().unwrap(),
        });
        let duplicate_filter = filter1.clone();

        // Test case 1: Add a new filter
        assert!(store.add(filter1.clone()).is_ok());

        // Test case 2: Attempt to add the same filter again, which should fail as duplicate
        assert!(store.add(duplicate_filter.clone()).is_err());

        // Add another filter
        assert!(store.add(filter2.clone()).is_ok());

        // Test case 3: Attempt to add another filter, which should fail due to max filters reached
        let filter3 = Arc::new(TestFilter {
            id: FilterID::new().unwrap(),
        });
        assert!(store.add(filter3.clone()).is_err());
    }
}