Skip to content

Commit

Permalink
Handle require_network validation with de::Error
Browse files Browse the repository at this point in the history
require_network always returns `ParseError` but conversion
to UriError to de::Error allows require_network and deserialization
to be handled in one function with one error variant.
  • Loading branch information
DanGould committed Aug 1, 2024
1 parent 5b41062 commit 23c26cb
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 32 deletions.
34 changes: 34 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ enum UriErrorInner {
TooShort,
InvalidScheme,
Address(AddressError),
AddressNetwork(bitcoin::address::Error),
Amount(ParseAmountError),
UnknownRequiredParameter(String),
PercentDecode {
Expand Down Expand Up @@ -255,6 +256,7 @@ impl fmt::Display for UriError {
UriErrorInner::TooShort => write!(f, "the URI is too short"),
UriErrorInner::InvalidScheme => write!(f, "the URI has invalid scheme"),
UriErrorInner::Address(_) => write!(f, "the address is invalid"),
UriErrorInner::AddressNetwork(_) => write!(f, "the address network is invalid"),
UriErrorInner::Amount(_) => write!(f, "the amount is invalid"),
UriErrorInner::UnknownRequiredParameter(parameter) => write!(f, "the URI contains unknown required parameter '{}'", parameter),
#[cfg(feature = "std")]
Expand All @@ -274,6 +276,7 @@ impl std::error::Error for UriError {
UriErrorInner::TooShort => None,
UriErrorInner::InvalidScheme => None,
UriErrorInner::Address(error) => Some(error),
UriErrorInner::AddressNetwork(error) => Some(error),
UriErrorInner::Amount(error) => Some(error),
UriErrorInner::UnknownRequiredParameter(_) => None,
UriErrorInner::PercentDecode { parameter: _, error } => Some(error),
Expand Down Expand Up @@ -319,3 +322,34 @@ impl<'a, T: for<'de> DeserializeParams<'de>> TryFrom<Cow<'a, str>> for Uri<'a, b
}
}
}

impl<'a, T: DeserializeParams<'a>> Uri<'a, bitcoin::address::NetworkUnchecked, T> {
/// Checks whether network of this address is as required.
///
/// For details about this mechanism, see section [*parsing addresses*](bitcoin::Address#parsing-addresses) on [`bitcoin::Address`].
pub fn require_network(self, network: bitcoin::Network) -> Result<Uri<'a, bitcoin::address::NetworkChecked, T>, Error<T::Error>> {
let address = self
.address
.require_network(network)
.map_err(UriErrorInner::AddressNetwork)
.map_err(Error::uri)?;
Ok(Uri {
address,
amount: self.amount,
label: self.label,
message: self.message,
extras: self.extras,
})
}

/// Marks URI validated without checks.
pub fn assume_checked(self) -> Uri<'a, bitcoin::address::NetworkChecked, T> {
Uri {
address: self.address.assume_checked(),
amount: self.amount,
label: self.label,
message: self.message,
extras: self.extras,
}
}
}
32 changes: 0 additions & 32 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,38 +134,6 @@ impl<'a, NetVal: NetworkValidation, T> Uri<'a, NetVal, T> {
}
}

impl<'a, T> Uri<'a, bitcoin::address::NetworkUnchecked, T> {
/// Checks that the bitcoin network in the URI is `network`.
pub fn require_network(self, network: bitcoin::Network) -> Result<Uri<'a, bitcoin::address::NetworkChecked, T>, InvalidNetworkError> {
if self.address.is_valid_for_network(network) {
Ok(self.assume_checked())
} else {
Err(InvalidNetworkError {
required: network,
found: *self.address.network(),
})
}
}

/// Marks URI validated without checks.
pub fn assume_checked(self) -> Uri<'a, bitcoin::address::NetworkChecked, T> {
Uri {
address: self.address.assume_checked(),
amount: self.amount,
label: self.label,
message: self.message,
extras: self.extras,
}
}
}

/// An error returned when network validation fails.
#[derive(Debug, Clone)]
pub struct InvalidNetworkError {
required: bitcoin::Network,
found: bitcoin::Network,
}

/// Abstracted stringly parameter in the URI.
///
/// This type abstracts the parameter that may be encoded allowing lazy decoding, possibly even
Expand Down

0 comments on commit 23c26cb

Please sign in to comment.