use core::borrow::Borrow; use alloc::{borrow::Cow, boxed::Box, rc::Rc, sync::Arc}; use bitcoin::{Block, OutPoint, Transaction, TxOut}; /// Trait to do something with every txout contained in a structure. /// /// We would prefer just work with things that can give us a `Iterator` /// here but rust's type system makes it extremely hard to do this (without trait objects). pub trait ForEachTxOut { /// The provided closure `f` will called with each `outpoint/txout` pair. fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))); } impl ForEachTxOut for Block { fn for_each_txout(&self, mut f: impl FnMut((OutPoint, &TxOut))) { for tx in self.txdata.iter() { tx.for_each_txout(&mut f) } } } /// Trait for things that have a single [`Transaction`] in them. /// /// This alows polymorphism in structures such as [`TxGraph`] where `T` can be anything that /// implements `AsTransaction`. You might think that we could just use [`core::convert::AsRef`] for /// this but the problem is that we need to implement it on `Cow` where `T: AsTransaction` which /// we can't do with a foreign trait like `AsTransaction`. /// /// [`Transaction`]: bitcoin::Transaction /// [`TxGraph`]: crate::tx_graph::TxGraph pub trait AsTransaction { /// Get a reference to the transaction. fn as_tx(&self) -> &Transaction; } impl AsTransaction for Transaction { fn as_tx(&self) -> &Transaction { self } } impl AsTransaction for Rc { fn as_tx(&self) -> &Transaction { self.as_ref().as_tx() } } impl AsTransaction for Arc { fn as_tx(&self) -> &Transaction { self.as_ref().as_tx() } } impl AsTransaction for Box { fn as_tx(&self) -> &Transaction { self.as_ref().as_tx() } } impl<'a, T: AsTransaction + Clone> AsTransaction for Cow<'a, T> { fn as_tx(&self) -> &Transaction { as Borrow>::borrow(self).as_tx() } } impl ForEachTxOut for T where T: AsTransaction, { fn for_each_txout(&self, mut f: impl FnMut((OutPoint, &TxOut))) { let tx = self.as_tx(); let txid = tx.txid(); for (i, txout) in tx.output.iter().enumerate() { f(( OutPoint { txid, vout: i as u32, }, txout, )) } } } /// A trait like [`core::convert::Into`] for converting one thing into another. /// /// We use it to convert one transaction type into another so that an update for `T2` can be used on /// a `TxGraph` as long as `T2: IntoOwned`. /// /// We couldn't use `Into` because we needed to implement it for [`Cow<'a, T>`]. /// /// [`Cow<'a, T>`]: std::borrow::Cow pub trait IntoOwned { /// Converts the provided type into another (owned) type. fn into_owned(self) -> T; } impl IntoOwned for T { fn into_owned(self) -> T { self } } impl<'a, T: Clone> IntoOwned for Cow<'a, T> { fn into_owned(self) -> T { Cow::into_owned(self) } } impl<'a, T: Clone> IntoOwned for &'a T { fn into_owned(self) -> T { self.clone() } }