lumina_node/store/
either_store.rs

1use std::fmt::{self, Debug, Display};
2use std::ops::RangeBounds;
3
4use async_trait::async_trait;
5use celestia_types::ExtendedHeader;
6use celestia_types::hash::Hash;
7use cid::Cid;
8use libp2p::identity::Keypair;
9
10use crate::store::{BlockRanges, Result, SamplingMetadata, Store, VerifiedExtendedHeaders};
11
12/// Struct that can be used to build combinations of different [`Store`] types.
13///
14/// # Example
15///
16/// ```ignore
17/// type SuperStore = EitherStore<InMemoryStore, RedbStore>;
18/// ```
19pub enum EitherStore<L, R>
20where
21    L: Store,
22    R: Store,
23{
24    /// A value of type `L`.
25    Left(L),
26    /// A value of type `R`.
27    Right(R),
28}
29
30impl<L, R> EitherStore<L, R>
31where
32    L: Store,
33    R: Store,
34{
35    /// Returns true if value is the `Left` variant.
36    pub fn is_left(&self) -> bool {
37        match self {
38            EitherStore::Left(_) => true,
39            EitherStore::Right(_) => false,
40        }
41    }
42
43    /// Returns true if value is the `Right` variant.
44    pub fn is_right(&self) -> bool {
45        match self {
46            EitherStore::Left(_) => false,
47            EitherStore::Right(_) => true,
48        }
49    }
50
51    /// Returns a reference of the left side of `EitherStore<L, R>`.
52    pub fn left(&self) -> Option<&L> {
53        match self {
54            EitherStore::Left(store) => Some(store),
55            EitherStore::Right(_) => None,
56        }
57    }
58
59    /// Returns a reference of the right side of `EitherStore<L, R>`.
60    pub fn right(&self) -> Option<&R> {
61        match self {
62            EitherStore::Left(_) => None,
63            EitherStore::Right(store) => Some(store),
64        }
65    }
66
67    /// Returns a mutable reference of the left side of `EitherStore<L, R>`.
68    pub fn left_mut(&mut self) -> Option<&mut L> {
69        match self {
70            EitherStore::Left(store) => Some(store),
71            EitherStore::Right(_) => None,
72        }
73    }
74
75    /// Returns a mutable reference of the right side of `EitherStore<L, R>`.
76    pub fn right_mut(&mut self) -> Option<&mut R> {
77        match self {
78            EitherStore::Left(_) => None,
79            EitherStore::Right(store) => Some(store),
80        }
81    }
82
83    /// Returns the left side of `EitherStore<L, R>`.
84    pub fn into_left(self) -> Option<L> {
85        match self {
86            EitherStore::Left(store) => Some(store),
87            EitherStore::Right(_) => None,
88        }
89    }
90
91    /// Returns the right side of `EitherStore<L, R>`.
92    pub fn into_right(self) -> Option<R> {
93        match self {
94            EitherStore::Left(_) => None,
95            EitherStore::Right(store) => Some(store),
96        }
97    }
98}
99
100impl<L, R> Clone for EitherStore<L, R>
101where
102    L: Store + Clone,
103    R: Store + Clone,
104{
105    fn clone(&self) -> Self {
106        match self {
107            EitherStore::Left(store) => EitherStore::Left(store.clone()),
108            EitherStore::Right(store) => EitherStore::Right(store.clone()),
109        }
110    }
111
112    fn clone_from(&mut self, source: &Self) {
113        match source {
114            EitherStore::Left(source_store) => match self {
115                EitherStore::Left(self_store) => self_store.clone_from(source_store),
116                EitherStore::Right(_) => *self = EitherStore::Left(source_store.clone()),
117            },
118            EitherStore::Right(source_store) => match self {
119                EitherStore::Left(_) => *self = EitherStore::Right(source_store.clone()),
120                EitherStore::Right(self_store) => self_store.clone_from(source_store),
121            },
122        };
123    }
124}
125
126impl<L, R> Debug for EitherStore<L, R>
127where
128    L: Store + Debug,
129    R: Store + Debug,
130{
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        match self {
133            EitherStore::Left(store) => Debug::fmt(store, f),
134            EitherStore::Right(store) => Debug::fmt(store, f),
135        }
136    }
137}
138
139impl<L, R> Display for EitherStore<L, R>
140where
141    L: Store + Display,
142    R: Store + Display,
143{
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        match self {
146            EitherStore::Left(store) => Display::fmt(store, f),
147            EitherStore::Right(store) => Display::fmt(store, f),
148        }
149    }
150}
151
152macro_rules! call {
153    ($self:ident, $method:ident($($param:expr),*)) =>  {
154        match $self {
155            EitherStore::Left(store) => store.$method($($param),*).await,
156            EitherStore::Right(store) => store.$method($($param),*).await,
157        }
158    };
159}
160
161#[async_trait]
162impl<L, R> Store for EitherStore<L, R>
163where
164    L: Store,
165    R: Store,
166{
167    async fn get_head(&self) -> Result<ExtendedHeader> {
168        call!(self, get_head())
169    }
170
171    async fn get_by_hash(&self, hash: &Hash) -> Result<ExtendedHeader> {
172        call!(self, get_by_hash(hash))
173    }
174
175    async fn get_by_height(&self, height: u64) -> Result<ExtendedHeader> {
176        call!(self, get_by_height(height))
177    }
178
179    async fn wait_new_head(&self) -> u64 {
180        call!(self, wait_new_head())
181    }
182
183    async fn wait_height(&self, height: u64) -> Result<()> {
184        call!(self, wait_height(height))
185    }
186
187    async fn get_range<RB>(&self, range: RB) -> Result<Vec<ExtendedHeader>>
188    where
189        RB: RangeBounds<u64> + Send,
190    {
191        call!(self, get_range(range))
192    }
193
194    async fn head_height(&self) -> Result<u64> {
195        call!(self, head_height())
196    }
197
198    async fn has(&self, hash: &Hash) -> bool {
199        call!(self, has(hash))
200    }
201
202    async fn has_at(&self, height: u64) -> bool {
203        call!(self, has_at(height))
204    }
205
206    async fn update_sampling_metadata(&self, height: u64, cids: Vec<Cid>) -> Result<()> {
207        call!(self, update_sampling_metadata(height, cids))
208    }
209
210    async fn get_sampling_metadata(&self, height: u64) -> Result<Option<SamplingMetadata>> {
211        call!(self, get_sampling_metadata(height))
212    }
213
214    async fn mark_as_sampled(&self, height: u64) -> Result<()> {
215        call!(self, mark_as_sampled(height))
216    }
217
218    async fn insert<H>(&self, headers: H) -> Result<()>
219    where
220        H: TryInto<VerifiedExtendedHeaders> + Send,
221        <H as TryInto<VerifiedExtendedHeaders>>::Error: Display,
222    {
223        call!(self, insert(headers))
224    }
225
226    async fn get_stored_header_ranges(&self) -> Result<BlockRanges> {
227        call!(self, get_stored_header_ranges())
228    }
229
230    async fn get_sampled_ranges(&self) -> Result<BlockRanges> {
231        call!(self, get_sampled_ranges())
232    }
233
234    async fn get_pruned_ranges(&self) -> Result<BlockRanges> {
235        call!(self, get_pruned_ranges())
236    }
237
238    async fn remove_height(&self, height: u64) -> Result<()> {
239        call!(self, remove_height(height))
240    }
241
242    async fn get_identity(&self) -> Result<Keypair> {
243        call!(self, get_identity())
244    }
245
246    async fn close(self) -> Result<()> {
247        call!(self, close())
248    }
249}