units: Add all pedantic lints
Add all the pedantic lints to the repository by way of the repository manifest. Then enable these lints in the `units` manifest. Some things worth mentioning: - Fix `needless_pass_by_value` by adding derives to `FormatOptions`. - Fix lint `cast_lossless` using `cargo clippy --fix`` - While fixing `lint enum_glob_use` introduce a new style to the codebase; import enums using a single character. Doing so prevents namespace clashes, improves clarity, and maintains terseness. Audit: Use the following lints locally and audit all the warnings, they produce many false positives so we can't enable them permentently. - `cast_possible_truncation` - `cast_possible_lint` - `cast_sign_loss`
This commit is contained in:
parent
f4069fcd61
commit
5290a93a38
125
units/Cargo.toml
125
units/Cargo.toml
|
@ -34,3 +34,128 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(kani)'] }
|
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(kani)'] }
|
||||||
|
|
||||||
|
[lints.clippy]
|
||||||
|
# Exhaustive list of pedantic clippy lints
|
||||||
|
assigning_clones = "warn"
|
||||||
|
bool_to_int_with_if = "warn"
|
||||||
|
borrow_as_ptr = "warn"
|
||||||
|
case_sensitive_file_extension_comparisons = "warn"
|
||||||
|
cast_lossless = "warn"
|
||||||
|
cast_possible_truncation = "allow" # All casts should include a code comment (except test code).
|
||||||
|
cast_possible_wrap = "allow" # Same as above re code comment.
|
||||||
|
cast_precision_loss = "warn"
|
||||||
|
cast_ptr_alignment = "warn"
|
||||||
|
cast_sign_loss = "allow" # All casts should include a code comment (except in test code).
|
||||||
|
checked_conversions = "warn"
|
||||||
|
cloned_instead_of_copied = "warn"
|
||||||
|
copy_iterator = "warn"
|
||||||
|
default_trait_access = "warn"
|
||||||
|
doc_link_with_quotes = "warn"
|
||||||
|
doc_markdown = "warn"
|
||||||
|
empty_enum = "warn"
|
||||||
|
enum_glob_use = "warn"
|
||||||
|
expl_impl_clone_on_copy = "warn"
|
||||||
|
explicit_deref_methods = "warn"
|
||||||
|
explicit_into_iter_loop = "warn"
|
||||||
|
explicit_iter_loop = "warn"
|
||||||
|
filter_map_next = "warn"
|
||||||
|
flat_map_option = "warn"
|
||||||
|
float_cmp = "allow" # Bitcoin floats are typically limited to 8 decimal places and we want them exact.
|
||||||
|
fn_params_excessive_bools = "warn"
|
||||||
|
from_iter_instead_of_collect = "warn"
|
||||||
|
if_not_else = "warn"
|
||||||
|
ignored_unit_patterns = "warn"
|
||||||
|
implicit_clone = "warn"
|
||||||
|
implicit_hasher = "warn"
|
||||||
|
inconsistent_struct_constructor = "warn"
|
||||||
|
index_refutable_slice = "warn"
|
||||||
|
inefficient_to_string = "warn"
|
||||||
|
inline_always = "warn"
|
||||||
|
into_iter_without_iter = "warn"
|
||||||
|
invalid_upcast_comparisons = "warn"
|
||||||
|
items_after_statements = "warn"
|
||||||
|
iter_filter_is_ok = "warn"
|
||||||
|
iter_filter_is_some = "warn"
|
||||||
|
iter_not_returning_iterator = "warn"
|
||||||
|
iter_without_into_iter = "warn"
|
||||||
|
large_digit_groups = "warn"
|
||||||
|
large_futures = "warn"
|
||||||
|
large_stack_arrays = "warn"
|
||||||
|
large_types_passed_by_value = "warn"
|
||||||
|
linkedlist = "warn"
|
||||||
|
macro_use_imports = "warn"
|
||||||
|
manual_assert = "warn"
|
||||||
|
manual_instant_elapsed = "warn"
|
||||||
|
manual_is_power_of_two = "warn"
|
||||||
|
manual_is_variant_and = "warn"
|
||||||
|
manual_let_else = "warn"
|
||||||
|
manual_ok_or = "warn"
|
||||||
|
manual_string_new = "warn"
|
||||||
|
many_single_char_names = "warn"
|
||||||
|
map_unwrap_or = "warn"
|
||||||
|
match_bool = "allow" # Adds extra indentation and LOC.
|
||||||
|
match_on_vec_items = "warn"
|
||||||
|
match_same_arms = "allow" # Collapses things that are conceptually unrelated to each other.
|
||||||
|
match_wild_err_arm = "warn"
|
||||||
|
match_wildcard_for_single_variants = "warn"
|
||||||
|
maybe_infinite_iter = "warn"
|
||||||
|
mismatching_type_param_order = "warn"
|
||||||
|
missing_errors_doc = "allow" # TODO: Still needs considering.
|
||||||
|
missing_fields_in_debug = "warn"
|
||||||
|
missing_panics_doc = "allow" # TODO: Still needs considering.
|
||||||
|
must_use_candidate = "allow" # Useful for audit but many false positives.
|
||||||
|
mut_mut = "warn"
|
||||||
|
naive_bytecount = "warn"
|
||||||
|
needless_bitwise_bool = "warn"
|
||||||
|
needless_continue = "warn"
|
||||||
|
needless_for_each = "warn"
|
||||||
|
needless_pass_by_value = "warn"
|
||||||
|
needless_raw_string_hashes = "warn"
|
||||||
|
no_effect_underscore_binding = "warn"
|
||||||
|
no_mangle_with_rust_abi = "warn"
|
||||||
|
option_as_ref_cloned = "warn"
|
||||||
|
option_option = "warn"
|
||||||
|
ptr_as_ptr = "warn"
|
||||||
|
ptr_cast_constness = "warn"
|
||||||
|
pub_underscore_fields = "warn"
|
||||||
|
range_minus_one = "warn"
|
||||||
|
range_plus_one = "warn"
|
||||||
|
redundant_closure_for_method_calls = "warn"
|
||||||
|
redundant_else = "warn"
|
||||||
|
ref_as_ptr = "warn"
|
||||||
|
ref_binding_to_reference = "warn"
|
||||||
|
ref_option = "allow" # TODO: Still neds considering.
|
||||||
|
ref_option_ref = "warn"
|
||||||
|
return_self_not_must_use = "warn"
|
||||||
|
same_functions_in_if_condition = "warn"
|
||||||
|
semicolon_if_nothing_returned = "warn"
|
||||||
|
should_panic_without_expect = "warn"
|
||||||
|
similar_names = "allow" # Too many (subjectively) false positives.
|
||||||
|
single_char_pattern = "warn"
|
||||||
|
single_match_else = "warn"
|
||||||
|
stable_sort_primitive = "warn"
|
||||||
|
str_split_at_newline = "warn"
|
||||||
|
string_add_assign = "warn"
|
||||||
|
struct_excessive_bools = "warn"
|
||||||
|
struct_field_names = "warn"
|
||||||
|
too_many_lines = "warn"
|
||||||
|
transmute_ptr_to_ptr = "warn"
|
||||||
|
trivially_copy_pass_by_ref = "warn"
|
||||||
|
unchecked_duration_subtraction = "warn"
|
||||||
|
unicode_not_nfc = "warn"
|
||||||
|
uninlined_format_args = "allow" # This is a subjective style choice.
|
||||||
|
unnecessary_box_returns = "warn"
|
||||||
|
unnecessary_join = "warn"
|
||||||
|
unnecessary_literal_bound = "warn"
|
||||||
|
unnecessary_wraps = "warn"
|
||||||
|
unnested_or_patterns = "warn"
|
||||||
|
unreadable_literal = "warn"
|
||||||
|
unsafe_derive_deserialize = "warn"
|
||||||
|
unused_async = "warn"
|
||||||
|
unused_self = "warn"
|
||||||
|
used_underscore_binding = "warn"
|
||||||
|
used_underscore_items = "warn"
|
||||||
|
verbose_bit_mask = "warn"
|
||||||
|
wildcard_imports = "warn"
|
||||||
|
zero_sized_map_values = "warn"
|
||||||
|
|
|
@ -119,14 +119,15 @@ internals::impl_from_infallible!(ParseAmountErrorInner);
|
||||||
|
|
||||||
impl fmt::Display for ParseAmountError {
|
impl fmt::Display for ParseAmountError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use ParseAmountErrorInner::*;
|
use ParseAmountErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
OutOfRange(ref error) => write_err!(f, "amount out of range"; error),
|
E::OutOfRange(ref error) => write_err!(f, "amount out of range"; error),
|
||||||
TooPrecise(ref error) => write_err!(f, "amount has a too high precision"; error),
|
E::TooPrecise(ref error) => write_err!(f, "amount has a too high precision"; error),
|
||||||
MissingDigits(ref error) => write_err!(f, "the input has too few digits"; error),
|
E::MissingDigits(ref error) => write_err!(f, "the input has too few digits"; error),
|
||||||
InputTooLarge(ref error) => write_err!(f, "the input is too large"; error),
|
E::InputTooLarge(ref error) => write_err!(f, "the input is too large"; error),
|
||||||
InvalidCharacter(ref error) => write_err!(f, "invalid character in the input"; error),
|
E::InvalidCharacter(ref error) =>
|
||||||
|
write_err!(f, "invalid character in the input"; error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,14 +135,14 @@ impl fmt::Display for ParseAmountError {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for ParseAmountError {
|
impl std::error::Error for ParseAmountError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
use ParseAmountErrorInner::*;
|
use ParseAmountErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
TooPrecise(ref error) => Some(error),
|
E::TooPrecise(ref error) => Some(error),
|
||||||
InputTooLarge(ref error) => Some(error),
|
E::InputTooLarge(ref error) => Some(error),
|
||||||
OutOfRange(ref error) => Some(error),
|
E::OutOfRange(ref error) => Some(error),
|
||||||
MissingDigits(ref error) => Some(error),
|
E::MissingDigits(ref error) => Some(error),
|
||||||
InvalidCharacter(ref error) => Some(error),
|
E::InvalidCharacter(ref error) => Some(error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +158,7 @@ impl OutOfRangeError {
|
||||||
/// Returns the minimum and maximum allowed values for the type that was parsed.
|
/// Returns the minimum and maximum allowed values for the type that was parsed.
|
||||||
///
|
///
|
||||||
/// This can be used to give a hint to the user which values are allowed.
|
/// This can be used to give a hint to the user which values are allowed.
|
||||||
pub fn valid_range(&self) -> (i64, u64) {
|
pub fn valid_range(self) -> (i64, u64) {
|
||||||
match self.is_signed {
|
match self.is_signed {
|
||||||
true => (i64::MIN, i64::MAX as u64),
|
true => (i64::MIN, i64::MAX as u64),
|
||||||
false => (0, u64::MAX),
|
false => (0, u64::MAX),
|
||||||
|
@ -165,10 +166,10 @@ impl OutOfRangeError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the input value was large than the maximum allowed value.
|
/// Returns true if the input value was large than the maximum allowed value.
|
||||||
pub fn is_above_max(&self) -> bool { self.is_greater_than_max }
|
pub fn is_above_max(self) -> bool { self.is_greater_than_max }
|
||||||
|
|
||||||
/// Returns true if the input value was smaller than the minimum allowed value.
|
/// Returns true if the input value was smaller than the minimum allowed value.
|
||||||
pub fn is_below_min(&self) -> bool { !self.is_greater_than_max }
|
pub fn is_below_min(self) -> bool { !self.is_greater_than_max }
|
||||||
|
|
||||||
pub(crate) fn too_big(is_signed: bool) -> Self { Self { is_signed, is_greater_than_max: true } }
|
pub(crate) fn too_big(is_signed: bool) -> Self { Self { is_signed, is_greater_than_max: true } }
|
||||||
|
|
||||||
|
@ -321,11 +322,11 @@ internals::impl_from_infallible!(ParseDenominationError);
|
||||||
|
|
||||||
impl fmt::Display for ParseDenominationError {
|
impl fmt::Display for ParseDenominationError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use ParseDenominationError::*;
|
use ParseDenominationError as E;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Unknown(ref e) => write_err!(f, "denomination parse error"; e),
|
E::Unknown(ref e) => write_err!(f, "denomination parse error"; e),
|
||||||
PossiblyConfusing(ref e) => write_err!(f, "denomination parse error"; e),
|
E::PossiblyConfusing(ref e) => write_err!(f, "denomination parse error"; e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,10 +334,10 @@ impl fmt::Display for ParseDenominationError {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for ParseDenominationError {
|
impl std::error::Error for ParseDenominationError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
use ParseDenominationError::*;
|
use ParseDenominationError as E;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Unknown(_) | PossiblyConfusing(_) => None,
|
E::Unknown(_) | E::PossiblyConfusing(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,8 +124,8 @@ impl Denomination {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// These form are ambigous and could have many meanings. For example, M could denote Mega or Milli.
|
/// These form are ambigous and could have many meanings. For example, M could denote Mega or Milli.
|
||||||
/// If any of these forms are used, an error type PossiblyConfusingDenomination is returned.
|
/// If any of these forms are used, an error type `PossiblyConfusingDenomination` is returned.
|
||||||
const CONFUSING_FORMS: [&str; 6] = ["CBTC", "Cbtc", "MBTC", "Mbtc", "UBTC", "Ubtc"];
|
const CONFUSING_FORMS: [&str; 6] = ["CBTC", "Cbtc", "MBTC", "Mbtc", "UBTC", "Ubtc"];
|
||||||
|
|
||||||
impl fmt::Display for Denomination {
|
impl fmt::Display for Denomination {
|
||||||
|
@ -143,15 +143,15 @@ impl FromStr for Denomination {
|
||||||
/// letter that could be confused with centi, milli, or micro-bitcoin.
|
/// letter that could be confused with centi, milli, or micro-bitcoin.
|
||||||
/// - [`ParseDenominationError::Unknown`]: If an unknown denomination is used.
|
/// - [`ParseDenominationError::Unknown`]: If an unknown denomination is used.
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
use self::ParseDenominationError::*;
|
use self::ParseDenominationError as E;
|
||||||
|
|
||||||
if CONFUSING_FORMS.contains(&s) {
|
if CONFUSING_FORMS.contains(&s) {
|
||||||
return Err(PossiblyConfusing(PossiblyConfusingDenominationError(s.into())));
|
return Err(E::PossiblyConfusing(PossiblyConfusingDenominationError(s.into())));
|
||||||
};
|
};
|
||||||
|
|
||||||
let form = self::Denomination::forms(s);
|
let form = self::Denomination::forms(s);
|
||||||
|
|
||||||
form.ok_or_else(|| Unknown(UnknownDenominationError(s.into())))
|
form.ok_or_else(|| E::Unknown(UnknownDenominationError(s.into())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ fn parse_signed_to_satoshi(
|
||||||
Ok(0) => return Ok((is_negative, 0)),
|
Ok(0) => return Ok((is_negative, 0)),
|
||||||
_ =>
|
_ =>
|
||||||
return Err(InnerParseError::TooPrecise(TooPreciseError {
|
return Err(InnerParseError::TooPrecise(TooPreciseError {
|
||||||
position: position + is_negative as usize,
|
position: position + usize::from(is_negative),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ fn parse_signed_to_satoshi(
|
||||||
// Do `value = 10 * value + digit`, catching overflows.
|
// Do `value = 10 * value + digit`, catching overflows.
|
||||||
match 10_u64.checked_mul(value) {
|
match 10_u64.checked_mul(value) {
|
||||||
None => return Err(InnerParseError::Overflow { is_negative }),
|
None => return Err(InnerParseError::Overflow { is_negative }),
|
||||||
Some(val) => match val.checked_add((c as u8 - b'0') as u64) {
|
Some(val) => match val.checked_add(u64::from(c as u8 - b'0')) {
|
||||||
None => return Err(InnerParseError::Overflow { is_negative }),
|
None => return Err(InnerParseError::Overflow { is_negative }),
|
||||||
Some(val) => value = val,
|
Some(val) => value = val,
|
||||||
},
|
},
|
||||||
|
@ -247,7 +247,7 @@ fn parse_signed_to_satoshi(
|
||||||
Some(d) if d < max_decimals => Some(d + 1),
|
Some(d) if d < max_decimals => Some(d + 1),
|
||||||
_ =>
|
_ =>
|
||||||
return Err(InnerParseError::TooPrecise(TooPreciseError {
|
return Err(InnerParseError::TooPrecise(TooPreciseError {
|
||||||
position: i + is_negative as usize,
|
position: i + usize::from(is_negative),
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -258,13 +258,13 @@ fn parse_signed_to_satoshi(
|
||||||
_ =>
|
_ =>
|
||||||
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
|
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
|
||||||
invalid_char: '.',
|
invalid_char: '.',
|
||||||
position: i + is_negative as usize,
|
position: i + usize::from(is_negative),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
c =>
|
c =>
|
||||||
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
|
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
|
||||||
invalid_char: c,
|
invalid_char: c,
|
||||||
position: i + is_negative as usize,
|
position: i + usize::from(is_negative),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,6 +319,7 @@ fn split_amount_and_denomination(s: &str) -> Result<(&str, Denomination), ParseE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options given by `fmt::Formatter`
|
/// Options given by `fmt::Formatter`
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
struct FormatOptions {
|
struct FormatOptions {
|
||||||
fill: char,
|
fill: char,
|
||||||
align: Option<fmt::Alignment>,
|
align: Option<fmt::Alignment>,
|
||||||
|
@ -394,7 +395,7 @@ fn fmt_satoshi_in(
|
||||||
// We add the number of zeroes to the end
|
// We add the number of zeroes to the end
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
if satoshi > 0 {
|
if satoshi > 0 {
|
||||||
exp = precision as usize;
|
exp = precision as usize; // Cast ok, checked not negative above.
|
||||||
}
|
}
|
||||||
trailing_decimal_zeros = options.precision.unwrap_or(0);
|
trailing_decimal_zeros = options.precision.unwrap_or(0);
|
||||||
}
|
}
|
||||||
|
@ -406,7 +407,7 @@ fn fmt_satoshi_in(
|
||||||
if usize::from(precision) > format_precision {
|
if usize::from(precision) > format_precision {
|
||||||
// precision is u8 so in this branch options.precision() < 255 which fits in u32
|
// precision is u8 so in this branch options.precision() < 255 which fits in u32
|
||||||
let rounding_divisor =
|
let rounding_divisor =
|
||||||
10u64.pow(u32::from(precision) - format_precision as u32);
|
10u64.pow(u32::from(precision) - format_precision as u32); // Cast ok, commented above.
|
||||||
let remainder = satoshi % rounding_divisor;
|
let remainder = satoshi % rounding_divisor;
|
||||||
satoshi -= remainder;
|
satoshi -= remainder;
|
||||||
if remainder / (rounding_divisor / 10) >= 5 {
|
if remainder / (rounding_divisor / 10) >= 5 {
|
||||||
|
@ -424,7 +425,7 @@ fn fmt_satoshi_in(
|
||||||
norm_nb_decimals = usize::from(precision);
|
norm_nb_decimals = usize::from(precision);
|
||||||
while num_after_decimal_point % 10 == 0 {
|
while num_after_decimal_point % 10 == 0 {
|
||||||
norm_nb_decimals -= 1;
|
norm_nb_decimals -= 1;
|
||||||
num_after_decimal_point /= 10
|
num_after_decimal_point /= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// compute requested precision
|
// compute requested precision
|
||||||
|
|
|
@ -111,11 +111,11 @@ impl SignedAmount {
|
||||||
(false, sat) if sat > SignedAmount::MAX.to_sat() as u64 => Err(ParseAmountError(
|
(false, sat) if sat > SignedAmount::MAX.to_sat() as u64 => Err(ParseAmountError(
|
||||||
ParseAmountErrorInner::OutOfRange(OutOfRangeError::too_big(true)),
|
ParseAmountErrorInner::OutOfRange(OutOfRangeError::too_big(true)),
|
||||||
)),
|
)),
|
||||||
(false, sat) => Ok(SignedAmount(sat as i64)),
|
(false, sat) => Ok(SignedAmount(sat as i64)), // Cast ok, value in this arm does not wrap.
|
||||||
(true, sat) if sat > SignedAmount::MIN.to_sat().unsigned_abs() => Err(
|
(true, sat) if sat > SignedAmount::MIN.to_sat().unsigned_abs() => Err(
|
||||||
ParseAmountError(ParseAmountErrorInner::OutOfRange(OutOfRangeError::too_small())),
|
ParseAmountError(ParseAmountErrorInner::OutOfRange(OutOfRangeError::too_small())),
|
||||||
),
|
),
|
||||||
(true, sat) => Ok(SignedAmount(-(sat as i64))),
|
(true, sat) => Ok(SignedAmount(-(sat as i64))), // Cast ok, value in this arm does not wrap.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ impl SignedAmount {
|
||||||
if self.is_negative() {
|
if self.is_negative() {
|
||||||
Err(OutOfRangeError::negative())
|
Err(OutOfRangeError::negative())
|
||||||
} else {
|
} else {
|
||||||
Ok(Amount::from_sat(self.to_sat() as u64))
|
Ok(Amount::from_sat(self.to_sat() as u64)) // Cast ok, checked not negative above.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ fn test_overflows() {
|
||||||
// panic on overflow
|
// panic on overflow
|
||||||
let result = panic::catch_unwind(|| Amount::MAX + Amount::from_sat(1));
|
let result = panic::catch_unwind(|| Amount::MAX + Amount::from_sat(1));
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let result = panic::catch_unwind(|| Amount::from_sat(8446744073709551615) * 3);
|
let result = panic::catch_unwind(|| Amount::from_sat(8_446_744_073_709_551_615) * 3);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,16 +205,19 @@ fn floating_point() {
|
||||||
let sat = Amount::from_sat;
|
let sat = Amount::from_sat;
|
||||||
let ssat = SignedAmount::from_sat;
|
let ssat = SignedAmount::from_sat;
|
||||||
|
|
||||||
assert_eq!(f(11.22, D::Bitcoin), Ok(sat(1122000000)));
|
assert_eq!(f(11.22, D::Bitcoin), Ok(sat(1_122_000_000)));
|
||||||
assert_eq!(sf(-11.22, D::MilliBitcoin), Ok(ssat(-1122000)));
|
assert_eq!(sf(-11.22, D::MilliBitcoin), Ok(ssat(-1_122_000)));
|
||||||
assert_eq!(f(11.22, D::Bit), Ok(sat(1122)));
|
assert_eq!(f(11.22, D::Bit), Ok(sat(1122)));
|
||||||
assert_eq!(f(0.0001234, D::Bitcoin), Ok(sat(12340)));
|
assert_eq!(f(0.000_123_4, D::Bitcoin), Ok(sat(12_340)));
|
||||||
assert_eq!(sf(-0.00012345, D::Bitcoin), Ok(ssat(-12345)));
|
assert_eq!(sf(-0.000_123_45, D::Bitcoin), Ok(ssat(-12_345)));
|
||||||
|
|
||||||
assert_eq!(f(11.22, D::Satoshi), Err(TooPreciseError { position: 3 }.into()));
|
assert_eq!(f(11.22, D::Satoshi), Err(TooPreciseError { position: 3 }.into()));
|
||||||
assert_eq!(f(42.123456781, D::Bitcoin), Err(TooPreciseError { position: 11 }.into()));
|
assert_eq!(f(42.123_456_781, D::Bitcoin), Err(TooPreciseError { position: 11 }.into()));
|
||||||
assert_eq!(sf(-184467440738.0, D::Bitcoin), Err(OutOfRangeError::too_small().into()));
|
assert_eq!(sf(-184_467_440_738.0, D::Bitcoin), Err(OutOfRangeError::too_small().into()));
|
||||||
assert_eq!(f(18446744073709551617.0, D::Satoshi), Err(OutOfRangeError::too_big(false).into()));
|
assert_eq!(
|
||||||
|
f(18_446_744_073_709_551_617.0, D::Satoshi),
|
||||||
|
Err(OutOfRangeError::too_big(false).into())
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
f(Amount::MAX.to_float_in(D::Satoshi) + 1.0, D::Satoshi),
|
f(Amount::MAX.to_float_in(D::Satoshi) + 1.0, D::Satoshi),
|
||||||
|
@ -230,10 +233,10 @@ fn floating_point() {
|
||||||
assert_eq!(btc(2.5).to_float_in(D::Bitcoin), 2.5);
|
assert_eq!(btc(2.5).to_float_in(D::Bitcoin), 2.5);
|
||||||
assert_eq!(btc(-2.5).to_float_in(D::CentiBitcoin), -250.0);
|
assert_eq!(btc(-2.5).to_float_in(D::CentiBitcoin), -250.0);
|
||||||
assert_eq!(btc(-2.5).to_float_in(D::MilliBitcoin), -2500.0);
|
assert_eq!(btc(-2.5).to_float_in(D::MilliBitcoin), -2500.0);
|
||||||
assert_eq!(btc(2.5).to_float_in(D::Satoshi), 250000000.0);
|
assert_eq!(btc(2.5).to_float_in(D::Satoshi), 250_000_000.0);
|
||||||
|
|
||||||
let btc = move |f| Amount::from_btc(f).unwrap();
|
let btc = move |f| Amount::from_btc(f).unwrap();
|
||||||
assert_eq!(&btc(0.0012).to_float_in(D::Bitcoin).to_string(), "0.0012")
|
assert_eq!(&btc(0.0012).to_float_in(D::Bitcoin).to_string(), "0.0012");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -508,6 +511,7 @@ fn test_unsigned_signed_conversion() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::inconsistent_digit_grouping)] // Group to show 100,000,000 sats per bitcoin.
|
#[allow(clippy::inconsistent_digit_grouping)] // Group to show 100,000,000 sats per bitcoin.
|
||||||
|
#[allow(clippy::items_after_statements)] // Define functions where we use them.
|
||||||
fn from_str() {
|
fn from_str() {
|
||||||
use ParseDenominationError::*;
|
use ParseDenominationError::*;
|
||||||
|
|
||||||
|
@ -577,7 +581,7 @@ fn from_str() {
|
||||||
|
|
||||||
ok_case(".5 bits", Amount::from_sat(50));
|
ok_case(".5 bits", Amount::from_sat(50));
|
||||||
ok_scase("-.5 bits", SignedAmount::from_sat(-50));
|
ok_scase("-.5 bits", SignedAmount::from_sat(-50));
|
||||||
ok_case("0.00253583 BTC", Amount::from_sat(253583));
|
ok_case("0.00253583 BTC", Amount::from_sat(253_583));
|
||||||
ok_scase("-5 satoshi", SignedAmount::from_sat(-5));
|
ok_scase("-5 satoshi", SignedAmount::from_sat(-5));
|
||||||
ok_case("0.10000000 BTC", Amount::from_sat(100_000_00));
|
ok_case("0.10000000 BTC", Amount::from_sat(100_000_00));
|
||||||
ok_scase("-100 bits", SignedAmount::from_sat(-10_000));
|
ok_scase("-100 bits", SignedAmount::from_sat(-10_000));
|
||||||
|
@ -596,23 +600,25 @@ fn to_from_string_in() {
|
||||||
let sa_str = SignedAmount::from_str_in;
|
let sa_str = SignedAmount::from_str_in;
|
||||||
let sa_sat = SignedAmount::from_sat;
|
let sa_sat = SignedAmount::from_sat;
|
||||||
|
|
||||||
assert_eq!("0.00253583", Amount::from_sat(253583).to_string_in(D::Bitcoin));
|
assert_eq!("0.5", Amount::from_sat(50).to_string_in(D::Bit));
|
||||||
assert_eq!("-0.00253583", SignedAmount::from_sat(-253583).to_string_in(D::Bitcoin));
|
assert_eq!("-0.5", SignedAmount::from_sat(-50).to_string_in(D::Bit));
|
||||||
|
assert_eq!("0.00253583", Amount::from_sat(253_583).to_string_in(D::Bitcoin));
|
||||||
|
assert_eq!("-5", SignedAmount::from_sat(-5).to_string_in(D::Satoshi));
|
||||||
assert_eq!("0.1", Amount::from_sat(100_000_00).to_string_in(D::Bitcoin));
|
assert_eq!("0.1", Amount::from_sat(100_000_00).to_string_in(D::Bitcoin));
|
||||||
assert_eq!("-0.1", SignedAmount::from_sat(-100_000_00).to_string_in(D::Bitcoin));
|
assert_eq!("-0.1", SignedAmount::from_sat(-100_000_00).to_string_in(D::Bitcoin));
|
||||||
|
|
||||||
assert_eq!("0.253583", Amount::from_sat(253583).to_string_in(D::CentiBitcoin));
|
assert_eq!("0.253583", Amount::from_sat(253_583).to_string_in(D::CentiBitcoin));
|
||||||
assert_eq!("-0.253583", SignedAmount::from_sat(-253583).to_string_in(D::CentiBitcoin));
|
assert_eq!("-0.253583", SignedAmount::from_sat(-253_583).to_string_in(D::CentiBitcoin));
|
||||||
assert_eq!("10", Amount::from_sat(100_000_00).to_string_in(D::CentiBitcoin));
|
assert_eq!("10", Amount::from_sat(100_000_00).to_string_in(D::CentiBitcoin));
|
||||||
assert_eq!("-10", SignedAmount::from_sat(-100_000_00).to_string_in(D::CentiBitcoin));
|
assert_eq!("-10", SignedAmount::from_sat(-100_000_00).to_string_in(D::CentiBitcoin));
|
||||||
|
|
||||||
assert_eq!("2.53583", Amount::from_sat(253583).to_string_in(D::MilliBitcoin));
|
assert_eq!("2.53583", Amount::from_sat(253_583).to_string_in(D::MilliBitcoin));
|
||||||
assert_eq!("-2.53583", SignedAmount::from_sat(-253583).to_string_in(D::MilliBitcoin));
|
assert_eq!("-2.53583", SignedAmount::from_sat(-253_583).to_string_in(D::MilliBitcoin));
|
||||||
assert_eq!("100", Amount::from_sat(100_000_00).to_string_in(D::MilliBitcoin));
|
assert_eq!("100", Amount::from_sat(100_000_00).to_string_in(D::MilliBitcoin));
|
||||||
assert_eq!("-100", SignedAmount::from_sat(-100_000_00).to_string_in(D::MilliBitcoin));
|
assert_eq!("-100", SignedAmount::from_sat(-100_000_00).to_string_in(D::MilliBitcoin));
|
||||||
|
|
||||||
assert_eq!("2535.83", Amount::from_sat(253583).to_string_in(D::MicroBitcoin));
|
assert_eq!("2535.83", Amount::from_sat(253_583).to_string_in(D::MicroBitcoin));
|
||||||
assert_eq!("-2535.83", SignedAmount::from_sat(-253583).to_string_in(D::MicroBitcoin));
|
assert_eq!("-2535.83", SignedAmount::from_sat(-253_583).to_string_in(D::MicroBitcoin));
|
||||||
assert_eq!("100000", Amount::from_sat(100_000_00).to_string_in(D::MicroBitcoin));
|
assert_eq!("100000", Amount::from_sat(100_000_00).to_string_in(D::MicroBitcoin));
|
||||||
assert_eq!("-100000", SignedAmount::from_sat(-100_000_00).to_string_in(D::MicroBitcoin));
|
assert_eq!("-100000", SignedAmount::from_sat(-100_000_00).to_string_in(D::MicroBitcoin));
|
||||||
|
|
||||||
|
@ -699,13 +705,13 @@ fn serde_as_sat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_test::assert_tokens(
|
serde_test::assert_tokens(
|
||||||
&T { amt: Amount::from_sat(123456789), samt: SignedAmount::from_sat(-123456789) },
|
&T { amt: Amount::from_sat(123_456_789), samt: SignedAmount::from_sat(-123_456_789) },
|
||||||
&[
|
&[
|
||||||
serde_test::Token::Struct { name: "T", len: 2 },
|
serde_test::Token::Struct { name: "T", len: 2 },
|
||||||
serde_test::Token::Str("amt"),
|
serde_test::Token::Str("amt"),
|
||||||
serde_test::Token::U64(123456789),
|
serde_test::Token::U64(123_456_789),
|
||||||
serde_test::Token::Str("samt"),
|
serde_test::Token::Str("samt"),
|
||||||
serde_test::Token::I64(-123456789),
|
serde_test::Token::I64(-123_456_789),
|
||||||
serde_test::Token::StructEnd,
|
serde_test::Token::StructEnd,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -763,7 +769,7 @@ fn serde_as_str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_test::assert_tokens(
|
serde_test::assert_tokens(
|
||||||
&T { amt: Amount::from_sat(123456789), samt: SignedAmount::from_sat(-123456789) },
|
&T { amt: Amount::from_sat(123_456_789), samt: SignedAmount::from_sat(-123_456_789) },
|
||||||
&[
|
&[
|
||||||
serde_test::Token::Struct { name: "T", len: 2 },
|
serde_test::Token::Struct { name: "T", len: 2 },
|
||||||
serde_test::Token::String("amt"),
|
serde_test::Token::String("amt"),
|
||||||
|
@ -797,10 +803,10 @@ fn serde_as_btc_opt() {
|
||||||
let without = T { amt: None, samt: None };
|
let without = T { amt: None, samt: None };
|
||||||
|
|
||||||
// Test Roundtripping
|
// Test Roundtripping
|
||||||
for s in [&with, &without].iter() {
|
for s in [&with, &without] {
|
||||||
let v = serde_json::to_string(s).unwrap();
|
let v = serde_json::to_string(s).unwrap();
|
||||||
let w: T = serde_json::from_str(&v).unwrap();
|
let w: T = serde_json::from_str(&v).unwrap();
|
||||||
assert_eq!(w, **s);
|
assert_eq!(w, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let t: T = serde_json::from_str("{\"amt\": 2.5, \"samt\": -2.5}").unwrap();
|
let t: T = serde_json::from_str("{\"amt\": 2.5, \"samt\": -2.5}").unwrap();
|
||||||
|
@ -839,10 +845,10 @@ fn serde_as_sat_opt() {
|
||||||
let without = T { amt: None, samt: None };
|
let without = T { amt: None, samt: None };
|
||||||
|
|
||||||
// Test Roundtripping
|
// Test Roundtripping
|
||||||
for s in [&with, &without].iter() {
|
for s in [&with, &without] {
|
||||||
let v = serde_json::to_string(s).unwrap();
|
let v = serde_json::to_string(s).unwrap();
|
||||||
let w: T = serde_json::from_str(&v).unwrap();
|
let w: T = serde_json::from_str(&v).unwrap();
|
||||||
assert_eq!(w, **s);
|
assert_eq!(w, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let t: T = serde_json::from_str("{\"amt\": 250000000, \"samt\": -250000000}").unwrap();
|
let t: T = serde_json::from_str("{\"amt\": 250000000, \"samt\": -250000000}").unwrap();
|
||||||
|
@ -875,16 +881,16 @@ fn serde_as_str_opt() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let with = T {
|
let with = T {
|
||||||
amt: Some(Amount::from_sat(123456789)),
|
amt: Some(Amount::from_sat(123_456_789)),
|
||||||
samt: Some(SignedAmount::from_sat(-123456789)),
|
samt: Some(SignedAmount::from_sat(-123_456_789)),
|
||||||
};
|
};
|
||||||
let without = T { amt: None, samt: None };
|
let without = T { amt: None, samt: None };
|
||||||
|
|
||||||
// Test Roundtripping
|
// Test Roundtripping
|
||||||
for s in [&with, &without].iter() {
|
for s in [&with, &without] {
|
||||||
let v = serde_json::to_string(s).unwrap();
|
let v = serde_json::to_string(s).unwrap();
|
||||||
let w: T = serde_json::from_str(&v).unwrap();
|
let w: T = serde_json::from_str(&v).unwrap();
|
||||||
assert_eq!(w, **s);
|
assert_eq!(w, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let t: T =
|
let t: T =
|
||||||
|
@ -953,7 +959,7 @@ fn denomination_string_acceptable_forms() {
|
||||||
"BTC", "btc", "cBTC", "cbtc", "mBTC", "mbtc", "uBTC", "ubtc", "bit", "bits", "BIT", "BITS",
|
"BTC", "btc", "cBTC", "cbtc", "mBTC", "mbtc", "uBTC", "ubtc", "bit", "bits", "BIT", "BITS",
|
||||||
"SATOSHI", "satoshi", "SATOSHIS", "satoshis", "SAT", "sat", "SATS", "sats",
|
"SATOSHI", "satoshi", "SATOSHIS", "satoshis", "SAT", "sat", "SATS", "sats",
|
||||||
];
|
];
|
||||||
for denom in valid.iter() {
|
for denom in valid {
|
||||||
assert!(denom.parse::<Denomination>().is_ok());
|
assert!(denom.parse::<Denomination>().is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -961,7 +967,7 @@ fn denomination_string_acceptable_forms() {
|
||||||
#[test]
|
#[test]
|
||||||
fn disallow_confusing_forms() {
|
fn disallow_confusing_forms() {
|
||||||
let confusing = ["CBTC", "Cbtc", "MBTC", "Mbtc", "UBTC", "Ubtc"];
|
let confusing = ["CBTC", "Cbtc", "MBTC", "Mbtc", "UBTC", "Ubtc"];
|
||||||
for denom in confusing.iter() {
|
for denom in confusing {
|
||||||
match denom.parse::<Denomination>() {
|
match denom.parse::<Denomination>() {
|
||||||
Ok(_) => panic!("from_str should error for {}", denom),
|
Ok(_) => panic!("from_str should error for {}", denom),
|
||||||
Err(ParseDenominationError::PossiblyConfusing(_)) => {}
|
Err(ParseDenominationError::PossiblyConfusing(_)) => {}
|
||||||
|
@ -974,7 +980,7 @@ fn disallow_confusing_forms() {
|
||||||
fn disallow_unknown_denomination() {
|
fn disallow_unknown_denomination() {
|
||||||
// Non-exhaustive list of unknown forms.
|
// Non-exhaustive list of unknown forms.
|
||||||
let unknown = ["NBTC", "ABC", "abc", "mSat", "msat"];
|
let unknown = ["NBTC", "ABC", "abc", "mSat", "msat"];
|
||||||
for denom in unknown.iter() {
|
for denom in unknown {
|
||||||
match denom.parse::<Denomination>() {
|
match denom.parse::<Denomination>() {
|
||||||
Ok(_) => panic!("from_str should error for {}", denom),
|
Ok(_) => panic!("from_str should error for {}", denom),
|
||||||
Err(ParseDenominationError::Unknown(_)) => (),
|
Err(ParseDenominationError::Unknown(_)) => (),
|
||||||
|
@ -986,7 +992,7 @@ fn disallow_unknown_denomination() {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
fn trailing_zeros_for_amount() {
|
fn trailing_zeros_for_amount() {
|
||||||
assert_eq!(format!("{}", Amount::from_sat(1000000)), "0.01 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(1_000_000)), "0.01 BTC");
|
||||||
assert_eq!(format!("{}", Amount::ONE_SAT), "0.00000001 BTC");
|
assert_eq!(format!("{}", Amount::ONE_SAT), "0.00000001 BTC");
|
||||||
assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC");
|
assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC");
|
||||||
assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC");
|
||||||
|
|
|
@ -414,11 +414,12 @@ impl Amount {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If the amount is too big.
|
/// If the amount is too big.
|
||||||
|
#[rustfmt::skip] // Moves code comments to the wrong line.
|
||||||
pub fn to_signed(self) -> Result<SignedAmount, OutOfRangeError> {
|
pub fn to_signed(self) -> Result<SignedAmount, OutOfRangeError> {
|
||||||
if self.to_sat() > SignedAmount::MAX.to_sat() as u64 {
|
if self.to_sat() > SignedAmount::MAX.to_sat() as u64 { // Cast ok, signed max is positive and fits in u64.
|
||||||
Err(OutOfRangeError::too_big(true))
|
Err(OutOfRangeError::too_big(true))
|
||||||
} else {
|
} else {
|
||||||
Ok(SignedAmount::from_sat(self.to_sat() as i64))
|
Ok(SignedAmount::from_sat(self.to_sat() as i64)) // Cast ok, checked not too big above.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,10 +148,10 @@ impl TryFrom<BlockInterval> for relative::Height {
|
||||||
/// [`BlockInterval`] is a thin wrapper around a `u32`, the two types are not interchangeable.
|
/// [`BlockInterval`] is a thin wrapper around a `u32`, the two types are not interchangeable.
|
||||||
fn try_from(h: BlockInterval) -> Result<Self, Self::Error> {
|
fn try_from(h: BlockInterval) -> Result<Self, Self::Error> {
|
||||||
let h = h.to_u32();
|
let h = h.to_u32();
|
||||||
if h > u16::MAX as u32 {
|
if h > u32::from(u16::MAX) {
|
||||||
return Err(TooBigForRelativeBlockHeightError(h));
|
return Err(TooBigForRelativeBlockHeightError(h));
|
||||||
}
|
}
|
||||||
Ok(relative::Height::from(h as u16)) // Cast ok, value checked above
|
Ok(relative::Height::from(h as u16)) // Cast ok, value checked above.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -356,7 +356,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[should_panic]
|
#[should_panic = "attempt to multiply with overflow"]
|
||||||
fn from_sat_per_vb_unchecked_panic() { FeeRate::from_sat_per_vb_unchecked(u64::MAX); }
|
fn from_sat_per_vb_unchecked_panic() { FeeRate::from_sat_per_vb_unchecked(u64::MAX); }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(deprecated_in_future)]
|
#![warn(deprecated_in_future)]
|
||||||
#![doc(test(attr(warn(unused))))]
|
#![doc(test(attr(warn(unused))))]
|
||||||
// Pedantic lints that we enforce.
|
|
||||||
#![warn(clippy::return_self_not_must_use)]
|
|
||||||
// Exclude lints we don't think are valuable.
|
// Exclude lints we don't think are valuable.
|
||||||
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
|
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
|
||||||
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
|
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
|
||||||
|
@ -27,7 +25,7 @@ mod internal_macros;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod _export {
|
pub mod _export {
|
||||||
/// A re-export of core::*
|
/// A re-export of `core::*`.
|
||||||
pub mod _core {
|
pub mod _core {
|
||||||
pub use core::*;
|
pub use core::*;
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,11 +285,13 @@ enum LockTimeUnit {
|
||||||
|
|
||||||
impl fmt::Display for LockTimeUnit {
|
impl fmt::Display for LockTimeUnit {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use LockTimeUnit::*;
|
use LockTimeUnit as L;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Blocks => write!(f, "expected lock-by-blockheight (must be < {})", LOCK_TIME_THRESHOLD),
|
L::Blocks =>
|
||||||
Seconds => write!(f, "expected lock-by-blocktime (must be >= {})", LOCK_TIME_THRESHOLD),
|
write!(f, "expected lock-by-blockheight (must be < {})", LOCK_TIME_THRESHOLD),
|
||||||
|
L::Seconds =>
|
||||||
|
write!(f, "expected lock-by-blocktime (must be >= {})", LOCK_TIME_THRESHOLD),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,10 +323,10 @@ impl ParseError {
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
use core::num::IntErrorKind;
|
use core::num::IntErrorKind;
|
||||||
|
|
||||||
use ParseError::*;
|
use ParseError as E;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
||||||
if *source.kind() == IntErrorKind::PosOverflow =>
|
if *source.kind() == IntErrorKind::PosOverflow =>
|
||||||
{
|
{
|
||||||
// Outputs "failed to parse <input_string> as absolute Height/Time (<subject> is above limit <upper_bound>)"
|
// Outputs "failed to parse <input_string> as absolute Height/Time (<subject> is above limit <upper_bound>)"
|
||||||
|
@ -336,7 +338,7 @@ impl ParseError {
|
||||||
upper_bound
|
upper_bound
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
||||||
if *source.kind() == IntErrorKind::NegOverflow =>
|
if *source.kind() == IntErrorKind::NegOverflow =>
|
||||||
{
|
{
|
||||||
// Outputs "failed to parse <input_string> as absolute Height/Time (<subject> is below limit <lower_bound>)"
|
// Outputs "failed to parse <input_string> as absolute Height/Time (<subject> is below limit <lower_bound>)"
|
||||||
|
@ -348,13 +350,13 @@ impl ParseError {
|
||||||
lower_bound
|
lower_bound
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ParseInt(ParseIntError { input, bits: _, is_signed: _, source: _ }) => {
|
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source: _ }) => {
|
||||||
write!(f, "{} ({})", input.display_cannot_parse("absolute Height/Time"), subject)
|
write!(f, "{} ({})", input.display_cannot_parse("absolute Height/Time"), subject)
|
||||||
}
|
}
|
||||||
Conversion(value) if *value < i64::from(lower_bound) => {
|
E::Conversion(value) if *value < i64::from(lower_bound) => {
|
||||||
write!(f, "{} {} is below limit {}", subject, value, lower_bound)
|
write!(f, "{} {} is below limit {}", subject, value, lower_bound)
|
||||||
}
|
}
|
||||||
Conversion(value) => {
|
E::Conversion(value) => {
|
||||||
write!(f, "{} {} is above limit {}", subject, value, upper_bound)
|
write!(f, "{} {} is above limit {}", subject, value, upper_bound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,17 +367,17 @@ impl ParseError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
use core::num::IntErrorKind;
|
use core::num::IntErrorKind;
|
||||||
|
|
||||||
use ParseError::*;
|
use ParseError as E;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ParseInt(ParseIntError { source, .. })
|
E::ParseInt(ParseIntError { source, .. })
|
||||||
if *source.kind() == IntErrorKind::PosOverflow =>
|
if *source.kind() == IntErrorKind::PosOverflow =>
|
||||||
None,
|
None,
|
||||||
ParseInt(ParseIntError { source, .. })
|
E::ParseInt(ParseIntError { source, .. })
|
||||||
if *source.kind() == IntErrorKind::NegOverflow =>
|
if *source.kind() == IntErrorKind::NegOverflow =>
|
||||||
None,
|
None,
|
||||||
ParseInt(ParseIntError { source, .. }) => Some(source),
|
E::ParseInt(ParseIntError { source, .. }) => Some(source),
|
||||||
Conversion(_) => None,
|
E::Conversion(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,14 +396,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn time_from_str_hex_happy_path() {
|
fn time_from_str_hex_happy_path() {
|
||||||
let actual = Time::from_hex("0x6289C350").unwrap();
|
let actual = Time::from_hex("0x6289C350").unwrap();
|
||||||
let expected = Time::from_consensus(0x6289C350).unwrap();
|
let expected = Time::from_consensus(0x6289_C350).unwrap();
|
||||||
assert_eq!(actual, expected);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn time_from_str_hex_no_prefix_happy_path() {
|
fn time_from_str_hex_no_prefix_happy_path() {
|
||||||
let time = Time::from_hex("6289C350").unwrap();
|
let time = Time::from_hex("6289C350").unwrap();
|
||||||
assert_eq!(time, Time(0x6289C350));
|
assert_eq!(time, Time(0x6289_C350));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -84,7 +84,7 @@ impl Time {
|
||||||
pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
|
pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||||
let interval = seconds / 512;
|
let interval = seconds / 512;
|
||||||
if interval <= u16::MAX as u32 { // infallible cast, needed by const code
|
if interval <= u16::MAX as u32 { // infallible cast, needed by const code
|
||||||
Ok(Time::from_512_second_intervals(interval as u16)) // cast checked above, needed by const code
|
Ok(Time::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||||
} else {
|
} else {
|
||||||
Err(TimeOverflowError { seconds })
|
Err(TimeOverflowError { seconds })
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ impl Time {
|
||||||
pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
|
pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||||
if seconds <= u16::MAX as u32 * 512 {
|
if seconds <= u16::MAX as u32 * 512 {
|
||||||
let interval = (seconds + 511) / 512;
|
let interval = (seconds + 511) / 512;
|
||||||
Ok(Time::from_512_second_intervals(interval as u16)) // cast checked above, needed by const code
|
Ok(Time::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||||
} else {
|
} else {
|
||||||
Err(TimeOverflowError { seconds })
|
Err(TimeOverflowError { seconds })
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,11 +318,11 @@ internals::impl_from_infallible!(PrefixedHexErrorInner);
|
||||||
|
|
||||||
impl fmt::Display for PrefixedHexError {
|
impl fmt::Display for PrefixedHexError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use PrefixedHexErrorInner::*;
|
use PrefixedHexErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
MissingPrefix(ref e) => write_err!(f, "hex string is missing prefix"; e),
|
E::MissingPrefix(ref e) => write_err!(f, "hex string is missing prefix"; e),
|
||||||
ParseInt(ref e) => write_err!(f, "prefixed hex string invalid int"; e),
|
E::ParseInt(ref e) => write_err!(f, "prefixed hex string invalid int"; e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,11 +330,11 @@ impl fmt::Display for PrefixedHexError {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for PrefixedHexError {
|
impl std::error::Error for PrefixedHexError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
use PrefixedHexErrorInner::*;
|
use PrefixedHexErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
MissingPrefix(ref e) => Some(e),
|
E::MissingPrefix(ref e) => Some(e),
|
||||||
ParseInt(ref e) => Some(e),
|
E::ParseInt(ref e) => Some(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,11 +364,11 @@ internals::impl_from_infallible!(UnprefixedHexErrorInner);
|
||||||
|
|
||||||
impl fmt::Display for UnprefixedHexError {
|
impl fmt::Display for UnprefixedHexError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use UnprefixedHexErrorInner::*;
|
use UnprefixedHexErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
ContainsPrefix(ref e) => write_err!(f, "hex string is contains prefix"; e),
|
E::ContainsPrefix(ref e) => write_err!(f, "hex string is contains prefix"; e),
|
||||||
ParseInt(ref e) => write_err!(f, "hex string parse int"; e),
|
E::ParseInt(ref e) => write_err!(f, "hex string parse int"; e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,11 +376,11 @@ impl fmt::Display for UnprefixedHexError {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for UnprefixedHexError {
|
impl std::error::Error for UnprefixedHexError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
use UnprefixedHexErrorInner::*;
|
use UnprefixedHexErrorInner as E;
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
ContainsPrefix(ref e) => Some(e),
|
E::ContainsPrefix(ref e) => Some(e),
|
||||||
ParseInt(ref e) => Some(e),
|
E::ParseInt(ref e) => Some(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,14 +453,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_u128_from_hex_prefixed() {
|
fn parse_u128_from_hex_prefixed() {
|
||||||
let want = 3735928559;
|
let want = 3_735_928_559;
|
||||||
let got = hex_u128("0xdeadbeef").expect("failed to parse prefixed hex");
|
let got = hex_u128("0xdeadbeef").expect("failed to parse prefixed hex");
|
||||||
assert_eq!(got, want);
|
assert_eq!(got, want);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_u128_from_hex_no_prefix() {
|
fn parse_u128_from_hex_no_prefix() {
|
||||||
let want = 3735928559;
|
let want = 3_735_928_559;
|
||||||
let got = hex_u128("deadbeef").expect("failed to parse non-prefixed hex");
|
let got = hex_u128("deadbeef").expect("failed to parse non-prefixed hex");
|
||||||
assert_eq!(got, want);
|
assert_eq!(got, want);
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ impl<'a> core::iter::Sum<&'a Weight> for Weight {
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a Weight>,
|
I: Iterator<Item = &'a Weight>,
|
||||||
{
|
{
|
||||||
iter.cloned().sum()
|
iter.copied().sum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[should_panic]
|
#[should_panic = "attempt to multiply with overflow"]
|
||||||
fn from_vb_unchecked_panic() { Weight::from_vb_unchecked(u64::MAX); }
|
fn from_vb_unchecked_panic() { Weight::from_vb_unchecked(u64::MAX); }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue