Skip to content

Commit

Permalink
Accept qualified types in impl_from_* macros
Browse files Browse the repository at this point in the history
  • Loading branch information
DanGould committed Nov 15, 2024
1 parent a5551b2 commit 6e3b595
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 56 deletions.
88 changes: 35 additions & 53 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
use bitcoin::address::{NetworkChecked, NetworkUnchecked};
use bitcoin::consensus::{deserialize, serialize};
use bitcoin::Address as BitcoinAddress;
use bitcoin::Amount as BitcoinAmount;
use bitcoin::FeeRate as BitcoinFeeRate;
use bitcoin::ScriptBuf as BitcoinScriptBuf;
use bitcoin::Sequence;
use bitcoin::Transaction as BitcoinTransaction;
use bitcoin::TxIn as BitcoinTxIn;
use bitcoin::TxOut as BitcoinTxOut;

pub use bitcoin::BlockHash;
pub use bitcoin::Txid;
Expand All @@ -27,20 +19,21 @@ mod macros;
pub mod error;

#[derive(Debug, PartialEq, Eq, uniffi::Object)]
pub struct Address(BitcoinAddress<NetworkChecked>);
pub struct Address(bitcoin::Address<NetworkChecked>);

#[uniffi::export]
impl Address {
#[uniffi::constructor]
pub fn new(address: String, network: Network) -> Result<Self, AddressParseError> {
let parsed_address = BitcoinAddress::from_str(&address).map_err(AddressParseError::from)?;
let parsed_address =
bitcoin::Address::from_str(&address).map_err(AddressParseError::from)?;
let network_checked_address = parsed_address.require_network(network.into())?;
Ok(Address(network_checked_address))
}

#[uniffi::constructor]
pub fn from_script(script: Arc<Script>, network: Network) -> Result<Self, FromScriptError> {
let address = BitcoinAddress::from_script(
let address = bitcoin::Address::from_script(
&script.0.clone(),
Into::<bitcoin::Network>::into(network),
)?;
Expand All @@ -57,7 +50,7 @@ impl Address {

pub fn is_valid_for_network(&self, network: Network) -> bool {
let address_str = self.0.to_string();
if let Ok(unchecked_address) = address_str.parse::<BitcoinAddress<NetworkUnchecked>>() {
if let Ok(unchecked_address) = address_str.parse::<bitcoin::Address<NetworkUnchecked>>() {
unchecked_address.is_valid_for_network(network.into())
} else {
false
Expand All @@ -71,18 +64,17 @@ impl Display for Address {
}
}

type CheckedBitcoinAddress = BitcoinAddress<NetworkChecked>;
impl_from_core_type!(Address, CheckedBitcoinAddress);
impl_from_ffi_type!(Address, CheckedBitcoinAddress);
impl_from_core_type!(Address, bitcoin::Address<NetworkChecked>);
impl_from_ffi_type!(Address, bitcoin::Address<NetworkChecked>);

#[derive(Clone, Debug, uniffi::Object)]
pub struct FeeRate(pub BitcoinFeeRate);
pub struct FeeRate(pub bitcoin::FeeRate);

#[uniffi::export]
impl FeeRate {
#[uniffi::constructor]
pub fn from_sat_per_vb(sat_per_vb: u64) -> Result<Self, FeeRateError> {
let fee_rate: Option<BitcoinFeeRate> = BitcoinFeeRate::from_sat_per_vb(sat_per_vb);
let fee_rate: Option<bitcoin::FeeRate> = bitcoin::FeeRate::from_sat_per_vb(sat_per_vb);
match fee_rate {
Some(fee_rate) => Ok(FeeRate(fee_rate)),
None => Err(FeeRateError::ArithmeticOverflow),
Expand All @@ -91,7 +83,7 @@ impl FeeRate {

#[uniffi::constructor]
pub fn from_sat_per_kwu(sat_per_kwu: u64) -> Self {
FeeRate(BitcoinFeeRate::from_sat_per_kwu(sat_per_kwu))
FeeRate(bitcoin::FeeRate::from_sat_per_kwu(sat_per_kwu))
}

pub fn to_sat_per_vb_ceil(&self) -> u64 {
Expand All @@ -107,14 +99,15 @@ impl FeeRate {
}
}

impl_from_core_type!(FeeRate, BitcoinFeeRate);
impl_from_ffi_type!(FeeRate, BitcoinFeeRate);
impl_from_core_type!(FeeRate, bitcoin::FeeRate);
impl_from_ffi_type!(FeeRate, bitcoin::FeeRate);

#[derive(Clone, Debug, PartialEq, Eq, uniffi::Record)]
pub struct OutPoint {
pub txid: Txid,
pub vout: u32,
}

impl From<bitcoin::OutPoint> for OutPoint {
fn from(outpoint: bitcoin::OutPoint) -> Self {
OutPoint {
Expand All @@ -131,13 +124,13 @@ impl From<OutPoint> for bitcoin::OutPoint {
}

#[derive(Clone, Debug, PartialEq, Eq, uniffi::Object)]
pub struct Script(pub BitcoinScriptBuf);
pub struct Script(pub bitcoin::ScriptBuf);

#[uniffi::export]
impl Script {
#[uniffi::constructor]
pub fn new(raw_output_script: Vec<u8>) -> Self {
let script: BitcoinScriptBuf = raw_output_script.into();
let script: bitcoin::ScriptBuf = raw_output_script.into();
Script(script)
}

Expand All @@ -146,46 +139,46 @@ impl Script {
}
}

impl_from_core_type!(Script, BitcoinScriptBuf);
impl_from_ffi_type!(Script, BitcoinScriptBuf);
impl_from_core_type!(Script, bitcoin::ScriptBuf);
impl_from_ffi_type!(Script, bitcoin::ScriptBuf);

#[derive(Debug, Clone, uniffi::Record)]
pub struct TxOut {
pub value: Arc<Amount>,
pub script_pubkey: Arc<Script>,
}

impl From<BitcoinTxOut> for TxOut {
fn from(tx_out: BitcoinTxOut) -> Self {
impl From<bitcoin::TxOut> for TxOut {
fn from(tx_out: bitcoin::TxOut) -> Self {
TxOut {
value: Arc::new(Amount(tx_out.value)),
script_pubkey: Arc::new(Script(tx_out.script_pubkey)),
}
}
}

impl From<TxOut> for BitcoinTxOut {
impl From<TxOut> for bitcoin::TxOut {
fn from(tx_out: TxOut) -> Self {
BitcoinTxOut {
bitcoin::TxOut {
value: tx_out.value.0,
script_pubkey: tx_out.script_pubkey.0.clone(),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
pub struct Amount(pub BitcoinAmount);
pub struct Amount(pub bitcoin::Amount);

#[uniffi::export]
impl Amount {
#[uniffi::constructor]
pub fn from_sat(sat: u64) -> Self {
Amount(BitcoinAmount::from_sat(sat))
Amount(bitcoin::Amount::from_sat(sat))
}

#[uniffi::constructor]
pub fn from_btc(btc: f64) -> Result<Self, ParseAmountError> {
let bitcoin_amount = BitcoinAmount::from_btc(btc).map_err(ParseAmountError::from)?;
let bitcoin_amount = bitcoin::Amount::from_btc(btc).map_err(ParseAmountError::from)?;
Ok(Amount(bitcoin_amount))
}

Expand All @@ -198,8 +191,8 @@ impl Amount {
}
}

impl_from_core_type!(Amount, BitcoinAmount);
impl_from_ffi_type!(Amount, BitcoinAmount);
impl_from_core_type!(Amount, bitcoin::Amount);
impl_from_ffi_type!(Amount, bitcoin::Amount);

#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct TxIn {
Expand All @@ -209,8 +202,8 @@ pub struct TxIn {
pub witness: Vec<Vec<u8>>,
}

impl From<BitcoinTxIn> for TxIn {
fn from(tx_in: BitcoinTxIn) -> Self {
impl From<bitcoin::TxIn> for TxIn {
fn from(tx_in: bitcoin::TxIn) -> Self {
TxIn {
previous_output: tx_in.previous_output.into(),
script_sig: Arc::new(tx_in.script_sig.into()),
Expand All @@ -220,36 +213,25 @@ impl From<BitcoinTxIn> for TxIn {
}
}

impl From<&BitcoinTxIn> for TxIn {
fn from(tx_in: &BitcoinTxIn) -> Self {
TxIn {
previous_output: tx_in.previous_output.into(),
script_sig: Arc::new(tx_in.script_sig.clone().into()),
sequence: tx_in.sequence.0,
witness: tx_in.witness.to_vec(),
}
}
}

impl From<TxIn> for BitcoinTxIn {
impl From<TxIn> for bitcoin::TxIn {
fn from(tx_in: TxIn) -> Self {
BitcoinTxIn {
bitcoin::TxIn {
previous_output: tx_in.previous_output.into(),
script_sig: tx_in.script_sig.0.clone(),
sequence: Sequence(tx_in.sequence),
sequence: bitcoin::Sequence(tx_in.sequence),
witness: tx_in.witness.into(),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
pub struct Transaction(pub BitcoinTransaction);
pub struct Transaction(pub bitcoin::Transaction);

#[uniffi::export]
impl Transaction {
#[uniffi::constructor]
pub fn deserialize(transaction_bytes: &[u8]) -> Result<Self, EncodeError> {
let transaction: BitcoinTransaction = deserialize(transaction_bytes)?;
let transaction: bitcoin::Transaction = deserialize(transaction_bytes)?;
Ok(Transaction(transaction))
}

Expand Down Expand Up @@ -312,8 +294,8 @@ impl Transaction {
}
}

impl_from_core_type!(Transaction, BitcoinTransaction);
impl_from_ffi_type!(Transaction, BitcoinTransaction);
impl_from_core_type!(Transaction, bitcoin::Transaction);
impl_from_ffi_type!(Transaction, bitcoin::Transaction);

#[derive(Clone, Default, uniffi::Enum)]
#[non_exhaustive]
Expand Down
6 changes: 3 additions & 3 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
macro_rules! impl_from_core_type {
($ffi_type:ident, $core_type:ident) => {
($ffi_type:ty, $core_type:ty) => {
impl From<$core_type> for $ffi_type {
fn from(core_type: $core_type) -> Self {
$ffi_type(core_type)
Self(core_type)
}
}
};
}

macro_rules! impl_from_ffi_type {
($ffi_type:ident, $core_type:ident) => {
($ffi_type:ty, $core_type:ty) => {
impl From<$ffi_type> for $core_type {
fn from(ffi_type: $ffi_type) -> Self {
ffi_type.0
Expand Down

0 comments on commit 6e3b595

Please sign in to comment.