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