1use super::*;
50
51macro_rules! impl_from {
52 ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
53 $( $cfg )*
54 impl From<$from> for $to {
55 fn from(inner: $from) -> Self {
56 <$to>::$variant(inner)
57 }
58 }
59 };
60}
61
62macro_rules! impl_inner_method {
63 ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
64 #[allow(deprecated)]
65 match $self {
66 $enum_name::Memory(inner) => inner.$name( $($args, )* ),
67 #[cfg(feature = "key-value-db")]
68 $enum_name::Sled(inner) => inner.$name( $($args, )* ),
69 #[cfg(feature = "sqlite")]
70 $enum_name::Sqlite(inner) => inner.$name( $($args, )* ),
71 }
72 }
73}
74
75#[derive(Debug)]
81pub enum AnyDatabase {
82 Memory(memory::MemoryDatabase),
84 #[cfg(feature = "key-value-db")]
85 #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
86 Sled(sled::Tree),
88 #[cfg(feature = "sqlite")]
89 #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
90 Sqlite(sqlite::SqliteDatabase),
92}
93
94impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
95impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
96impl_from!(sqlite::SqliteDatabase, AnyDatabase, Sqlite, #[cfg(feature = "sqlite")]);
97
98pub enum AnyBatch {
100 Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
102 #[cfg(feature = "key-value-db")]
103 #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
104 Sled(<sled::Tree as BatchDatabase>::Batch),
106 #[cfg(feature = "sqlite")]
107 #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
108 Sqlite(<sqlite::SqliteDatabase as BatchDatabase>::Batch),
110}
111
112impl_from!(
113 <memory::MemoryDatabase as BatchDatabase>::Batch,
114 AnyBatch,
115 Memory,
116);
117impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
118impl_from!(<sqlite::SqliteDatabase as BatchDatabase>::Batch, AnyBatch, Sqlite, #[cfg(feature = "sqlite")]);
119
120impl BatchOperations for AnyDatabase {
121 fn set_script_pubkey(
122 &mut self,
123 script: &Script,
124 keychain: KeychainKind,
125 child: u32,
126 ) -> Result<(), Error> {
127 impl_inner_method!(
128 AnyDatabase,
129 self,
130 set_script_pubkey,
131 script,
132 keychain,
133 child
134 )
135 }
136 fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
137 impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
138 }
139 fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
140 impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
141 }
142 fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
143 impl_inner_method!(AnyDatabase, self, set_tx, transaction)
144 }
145 fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
146 impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
147 }
148 fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error> {
149 impl_inner_method!(AnyDatabase, self, set_sync_time, sync_time)
150 }
151
152 fn del_script_pubkey_from_path(
153 &mut self,
154 keychain: KeychainKind,
155 child: u32,
156 ) -> Result<Option<Script>, Error> {
157 impl_inner_method!(
158 AnyDatabase,
159 self,
160 del_script_pubkey_from_path,
161 keychain,
162 child
163 )
164 }
165 fn del_path_from_script_pubkey(
166 &mut self,
167 script: &Script,
168 ) -> Result<Option<(KeychainKind, u32)>, Error> {
169 impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
170 }
171 fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
172 impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
173 }
174 fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
175 impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
176 }
177 fn del_tx(
178 &mut self,
179 txid: &Txid,
180 include_raw: bool,
181 ) -> Result<Option<TransactionDetails>, Error> {
182 impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
183 }
184 fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
185 impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
186 }
187 fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
188 impl_inner_method!(AnyDatabase, self, del_sync_time)
189 }
190}
191
192impl Database for AnyDatabase {
193 fn check_descriptor_checksum<B: AsRef<[u8]>>(
194 &mut self,
195 keychain: KeychainKind,
196 bytes: B,
197 ) -> Result<(), Error> {
198 impl_inner_method!(
199 AnyDatabase,
200 self,
201 check_descriptor_checksum,
202 keychain,
203 bytes
204 )
205 }
206
207 fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
208 impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
209 }
210 fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
211 impl_inner_method!(AnyDatabase, self, iter_utxos)
212 }
213 fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
214 impl_inner_method!(AnyDatabase, self, iter_raw_txs)
215 }
216 fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
217 impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
218 }
219
220 fn get_script_pubkey_from_path(
221 &self,
222 keychain: KeychainKind,
223 child: u32,
224 ) -> Result<Option<Script>, Error> {
225 impl_inner_method!(
226 AnyDatabase,
227 self,
228 get_script_pubkey_from_path,
229 keychain,
230 child
231 )
232 }
233 fn get_path_from_script_pubkey(
234 &self,
235 script: &Script,
236 ) -> Result<Option<(KeychainKind, u32)>, Error> {
237 impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
238 }
239 fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
240 impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
241 }
242 fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
243 impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
244 }
245 fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
246 impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
247 }
248 fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
249 impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
250 }
251 fn get_sync_time(&self) -> Result<Option<SyncTime>, Error> {
252 impl_inner_method!(AnyDatabase, self, get_sync_time)
253 }
254
255 fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
256 impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
257 }
258}
259
260impl BatchOperations for AnyBatch {
261 fn set_script_pubkey(
262 &mut self,
263 script: &Script,
264 keychain: KeychainKind,
265 child: u32,
266 ) -> Result<(), Error> {
267 impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
268 }
269 fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
270 impl_inner_method!(AnyBatch, self, set_utxo, utxo)
271 }
272 fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
273 impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
274 }
275 fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
276 impl_inner_method!(AnyBatch, self, set_tx, transaction)
277 }
278 fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
279 impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
280 }
281 fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error> {
282 impl_inner_method!(AnyBatch, self, set_sync_time, sync_time)
283 }
284
285 fn del_script_pubkey_from_path(
286 &mut self,
287 keychain: KeychainKind,
288 child: u32,
289 ) -> Result<Option<Script>, Error> {
290 impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
291 }
292 fn del_path_from_script_pubkey(
293 &mut self,
294 script: &Script,
295 ) -> Result<Option<(KeychainKind, u32)>, Error> {
296 impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
297 }
298 fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
299 impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
300 }
301 fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
302 impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
303 }
304 fn del_tx(
305 &mut self,
306 txid: &Txid,
307 include_raw: bool,
308 ) -> Result<Option<TransactionDetails>, Error> {
309 impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
310 }
311 fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
312 impl_inner_method!(AnyBatch, self, del_last_index, keychain)
313 }
314 fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
315 impl_inner_method!(AnyBatch, self, del_sync_time)
316 }
317}
318
319impl BatchDatabase for AnyDatabase {
320 type Batch = AnyBatch;
321
322 fn begin_batch(&self) -> Self::Batch {
323 match self {
324 AnyDatabase::Memory(inner) => inner.begin_batch().into(),
325 #[cfg(feature = "key-value-db")]
326 AnyDatabase::Sled(inner) => inner.begin_batch().into(),
327 #[cfg(feature = "sqlite")]
328 AnyDatabase::Sqlite(inner) => inner.begin_batch().into(),
329 }
330 }
331 fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
332 match self {
333 AnyDatabase::Memory(db) => match batch {
334 AnyBatch::Memory(batch) => db.commit_batch(batch),
335 #[cfg(any(feature = "key-value-db", feature = "sqlite"))]
336 _ => unimplemented!("Other batch shouldn't be used with Memory db."),
337 },
338 #[cfg(feature = "key-value-db")]
339 AnyDatabase::Sled(db) => match batch {
340 AnyBatch::Sled(batch) => db.commit_batch(batch),
341 _ => unimplemented!("Other batch shouldn't be used with Sled db."),
342 },
343 #[cfg(feature = "sqlite")]
344 AnyDatabase::Sqlite(db) => match batch {
345 AnyBatch::Sqlite(batch) => db.commit_batch(batch),
346 _ => unimplemented!("Other batch shouldn't be used with Sqlite db."),
347 },
348 }
349 }
350}
351
352#[cfg(feature = "key-value-db")]
354#[derive(Debug, serde::Serialize, serde::Deserialize)]
355pub struct SledDbConfiguration {
356 pub path: String,
358 pub tree_name: String,
360}
361
362#[cfg(feature = "key-value-db")]
363impl ConfigurableDatabase for sled::Tree {
364 type Config = SledDbConfiguration;
365
366 fn from_config(config: &Self::Config) -> Result<Self, Error> {
367 Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
368 }
369}
370
371#[cfg(feature = "sqlite")]
373#[derive(Debug, serde::Serialize, serde::Deserialize)]
374pub struct SqliteDbConfiguration {
375 pub path: String,
377}
378
379#[cfg(feature = "sqlite")]
380impl ConfigurableDatabase for sqlite::SqliteDatabase {
381 type Config = SqliteDbConfiguration;
382
383 fn from_config(config: &Self::Config) -> Result<Self, Error> {
384 Ok(sqlite::SqliteDatabase::new(config.path.clone()))
385 }
386}
387
388#[derive(Debug, serde::Serialize, serde::Deserialize)]
394pub enum AnyDatabaseConfig {
395 Memory(()),
397 #[cfg(feature = "key-value-db")]
398 #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
399 Sled(SledDbConfiguration),
401 #[cfg(feature = "sqlite")]
402 #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
403 Sqlite(SqliteDbConfiguration),
405}
406
407impl ConfigurableDatabase for AnyDatabase {
408 type Config = AnyDatabaseConfig;
409
410 fn from_config(config: &Self::Config) -> Result<Self, Error> {
411 Ok(match config {
412 AnyDatabaseConfig::Memory(inner) => {
413 AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
414 }
415 #[cfg(feature = "key-value-db")]
416 AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
417 #[cfg(feature = "sqlite")]
418 AnyDatabaseConfig::Sqlite(inner) => {
419 AnyDatabase::Sqlite(sqlite::SqliteDatabase::from_config(inner)?)
420 }
421 })
422 }
423}
424
425impl_from!((), AnyDatabaseConfig, Memory,);
426impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
427impl_from!(SqliteDbConfiguration, AnyDatabaseConfig, Sqlite, #[cfg(feature = "sqlite")]);