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