cometbft_light_client/store/
memory.rs

1//! Transient in-memory store
2
3use std::collections::{btree_map::Entry::*, BTreeMap};
4
5use crate::{
6    store::{LightStore, Status},
7    verifier::types::{Height, LightBlock},
8};
9
10/// Internal entry for the memory store
11#[derive(Clone, Debug, PartialEq)]
12struct StoreEntry {
13    light_block: LightBlock,
14    status: Status,
15}
16
17impl StoreEntry {
18    fn new(light_block: LightBlock, status: Status) -> Self {
19        Self {
20            light_block,
21            status,
22        }
23    }
24}
25
26/// Transient in-memory store.
27#[derive(Debug, Clone, Default)]
28pub struct MemoryStore {
29    store: BTreeMap<Height, StoreEntry>,
30}
31
32impl MemoryStore {
33    /// Create a new, empty, in-memory store
34    pub fn new() -> Self {
35        Self {
36            store: BTreeMap::new(),
37        }
38    }
39}
40
41impl LightStore for MemoryStore {
42    fn get(&self, height: Height, status: Status) -> Option<LightBlock> {
43        self.store
44            .get(&height)
45            .filter(|e| e.status == status)
46            .cloned()
47            .map(|e| e.light_block)
48    }
49
50    fn insert(&mut self, light_block: LightBlock, status: Status) {
51        self.store
52            .insert(light_block.height(), StoreEntry::new(light_block, status));
53    }
54
55    fn remove(&mut self, height: Height, status: Status) {
56        if let Occupied(e) = self.store.entry(height) {
57            if e.get().status == status {
58                e.remove_entry();
59            }
60        }
61    }
62
63    fn update(&mut self, light_block: &LightBlock, status: Status) {
64        self.insert(light_block.clone(), status);
65    }
66
67    fn highest(&self, status: Status) -> Option<LightBlock> {
68        self.store
69            .iter()
70            .filter(|(_, e)| e.status == status)
71            .max_by_key(|(&height, _)| height)
72            .map(|(_, e)| e.light_block.clone())
73    }
74
75    fn highest_before(&self, height: Height, status: Status) -> Option<LightBlock> {
76        self.store
77            .iter()
78            .filter(|(_, e)| e.status == status)
79            .filter(|(h, _)| h <= &&height)
80            .max_by_key(|(&height, _)| height)
81            .map(|(_, e)| e.light_block.clone())
82    }
83
84    fn lowest(&self, status: Status) -> Option<LightBlock> {
85        self.store
86            .iter()
87            .filter(|(_, e)| e.status == status)
88            .min_by_key(|(&height, _)| height)
89            .map(|(_, e)| e.light_block.clone())
90    }
91
92    #[allow(clippy::needless_collect)]
93    fn all(&self, status: Status) -> Box<dyn Iterator<Item = LightBlock>> {
94        let light_blocks: Vec<_> = self
95            .store
96            .iter()
97            .filter(|(_, e)| e.status == status)
98            .map(|(_, e)| e.light_block.clone())
99            .collect();
100
101        Box::new(light_blocks.into_iter())
102    }
103}