Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
return Err(Error::Uri(UriError(UriErrorInner::TooShort)));
}

if !string.get(..SCHEME.len()).map_or(false, |s| s.eq_ignore_ascii_case(SCHEME)) {
if !string.get(..SCHEME.len()).is_some_and(|s| s.eq_ignore_ascii_case(SCHEME)) {

Check failure on line 28 in src/de.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 1.63.0)

use of unstable library feature 'is_some_with'
return Err(Error::Uri(UriError(UriErrorInner::InvalidScheme)));
}

Expand Down Expand Up @@ -60,14 +60,23 @@
let value = &param[(pos + 1)..];
match key {
"amount" => {
if amount.is_some() {
return Err(Error::Uri(UriError(UriErrorInner::DuplicateParameter(key.to_owned()))));
}
let parsed_amount = bitcoin::Amount::from_str_in(value, Denomination::Bitcoin).map_err(Error::uri)?;
amount = Some(parsed_amount);
},
"label" => {
if label.is_some() {
return Err(Error::Uri(UriError(UriErrorInner::DuplicateParameter(key.to_owned()))));
}
let label_decoder = Param::decode(value).map_err(Error::percent_decode_static("label"))?;
label = Some(label_decoder);
},
"message" => {
if message.is_some() {
return Err(Error::Uri(UriError(UriErrorInner::DuplicateParameter(key.to_owned()))));
}
let message_decoder = Param::decode(value).map_err(Error::percent_decode_static("message"))?;
message = Some(message_decoder);
},
Expand Down Expand Up @@ -240,6 +249,7 @@
InvalidScheme,
Address(AddressError),
Amount(ParseAmountError),
DuplicateParameter(String),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this could safely be &static str because the expected parameter keys are hard coded, undecided if I prefer this for simplicity & consistency with UnknownRequiredParameter which I think kinda needs to have a String since it makes sense for the error to outlive the erroneous input

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had this exact thought and went with String for consistency with UnknownRequiredParameter

UnknownRequiredParameter(String),
PercentDecode {
parameter: Cow<'static, str>,
Expand Down Expand Up @@ -267,6 +277,7 @@
UriErrorInner::InvalidScheme => write!(f, "the URI has invalid scheme"),
UriErrorInner::Address(_) => write!(f, "the address is invalid"),
UriErrorInner::Amount(_) => write!(f, "the amount is invalid"),
UriErrorInner::DuplicateParameter(parameter) => write!(f, "the URI contains a duplicate parameter '{}'", parameter),
UriErrorInner::UnknownRequiredParameter(parameter) => write!(f, "the URI contains unknown required parameter '{}'", parameter),
#[cfg(feature = "std")]
UriErrorInner::PercentDecode { parameter, error: _ } => write!(f, "can not percent-decode parameter {}", parameter),
Expand All @@ -286,6 +297,7 @@
UriErrorInner::InvalidScheme => None,
UriErrorInner::Address(error) => Some(error),
UriErrorInner::Amount(error) => Some(error),
UriErrorInner::DuplicateParameter(_) => None,
UriErrorInner::UnknownRequiredParameter(_) => None,
UriErrorInner::PercentDecode { parameter: _, error } => Some(error),
UriErrorInner::MissingEquals(_) => None,
Expand Down
17 changes: 16 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//!
//! * Rust-idiomatic: uses strong types, standard traits and other things
//! * Compliant: implements all requirements of BIP21, including protections to not forget about
//! `req-`. (But see features.)
//! `req-`. (But see features.)
//! * Flexible: enables parsing/serializing additional arguments not defined by BIP21
//! * Performant: uses zero-copy deserialization and lazy evaluation wherever possible.
//!
Expand Down Expand Up @@ -488,4 +488,19 @@ mod tests {
let uri = input.parse::<Uri<'_, _>>();
assert!(uri.is_err());
}

#[test]
fn duplicate_params() {
let duplicate_label = "bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?label=foo&label=bar";
let uri = duplicate_label.parse::<Uri<'_, _>>();
assert!(uri.is_err());

let duplicate_amount = "bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?amount=123&amount=456";
let uri = duplicate_amount.parse::<Uri<'_, _>>();
assert!(uri.is_err());

let duplicate_message = "bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?message=foo&message=bar";
let uri = duplicate_message.parse::<Uri<'_, _>>();
assert!(uri.is_err());
}
}
Loading