Implement `Debug` for generic `Address<V: NetworkValidation>`

Previously `Debug` was implemented for both `Address<NetworkChecked>`
and `Address<NetworkUnchecked>`, but not for cases when the
`NetworkValidation` parameter was generic. This change adds this
ability.
This commit is contained in:
Jiri Jakes 2023-01-22 16:23:10 +08:00
parent d66ee48482
commit ebfbe74243
1 changed files with 36 additions and 14 deletions

View File

@ -571,20 +571,23 @@ mod sealed {
/// Marker of status of address's network validation. See section [*Parsing addresses*](Address#parsing-addresses) /// Marker of status of address's network validation. See section [*Parsing addresses*](Address#parsing-addresses)
/// on [`Address`] for details. /// on [`Address`] for details.
pub trait NetworkValidation: sealed::NetworkValidation {} pub trait NetworkValidation: sealed::NetworkValidation {
/// Indicates whether this `NetworkValidation` is `NetworkChecked` or not.
const IS_CHECKED: bool;
}
/// Marker that address's network has been successfully validated. See section [*Parsing addresses*](Address#parsing-addresses) /// Marker that address's network has been successfully validated. See section [*Parsing addresses*](Address#parsing-addresses)
/// on [`Address`] for details. /// on [`Address`] for details.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NetworkChecked {} pub enum NetworkChecked {}
/// Marker that address's network has not yet been validated. See section [*Parsing addresses*](Address#parsing-addresses) /// Marker that address's network has not yet been validated. See section [*Parsing addresses*](Address#parsing-addresses)
/// on [`Address`] for details. /// on [`Address`] for details.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NetworkUnchecked {} pub enum NetworkUnchecked {}
impl NetworkValidation for NetworkChecked {} impl NetworkValidation for NetworkChecked { const IS_CHECKED: bool = true; }
impl NetworkValidation for NetworkUnchecked {} impl NetworkValidation for NetworkUnchecked { const IS_CHECKED: bool = false; }
/// A Bitcoin address. /// A Bitcoin address.
/// ///
@ -970,16 +973,16 @@ impl fmt::Display for Address {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.fmt_internal(fmt) } fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.fmt_internal(fmt) }
} }
impl fmt::Debug for Address { impl<V: NetworkValidation> fmt::Debug for Address<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_internal(f) }
}
impl fmt::Debug for Address<NetworkUnchecked> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if V::IS_CHECKED {
self.fmt_internal(f)
} else {
write!(f, "Address<NetworkUnchecked>(")?; write!(f, "Address<NetworkUnchecked>(")?;
self.fmt_internal(f)?; self.fmt_internal(f)?;
write!(f, ")") write!(f, ")")
} }
}
} }
struct UpperWriter<W: fmt::Write>(W); struct UpperWriter<W: fmt::Write>(W);
@ -1005,7 +1008,7 @@ fn find_bech32_prefix(bech32: &str) -> &str {
} }
} }
// Address can be parsed only with NetworkUnchecked. /// Address can be parsed only with `NetworkUnchecked`.
impl FromStr for Address<NetworkUnchecked> { impl FromStr for Address<NetworkUnchecked> {
type Err = Error; type Err = Error;
@ -1232,6 +1235,25 @@ mod tests {
roundtrips(&addr); roundtrips(&addr);
} }
#[test]
fn test_address_debug() {
// This is not really testing output of Debug but the ability and proper functioning
// of Debug derivation on structs generic in NetworkValidation.
#[derive(Debug)] #[allow(unused)]
struct Test<V: NetworkValidation> { address: Address<V> }
let addr_str = "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k";
let unchecked = Address::from_str(addr_str).unwrap();
assert_eq!(
format!("{:?}", Test { address: unchecked.clone() }),
format!("Test {{ address: Address<NetworkUnchecked>({}) }}", addr_str));
assert_eq!(
format!("{:?}", Test { address: unchecked.assume_checked() }),
format!("Test {{ address: {} }}", addr_str));
}
#[test] #[test]
fn test_address_type() { fn test_address_type() {
let addresses = [ let addresses = [