Mark functions `const` in `units`

Mark `checked_` functions const. Replace `map()` and `?` operators,
which are not allowed in const context, with match statements.
Use descriptive variable names in ceiling division to make
it easier to follow.
This commit is contained in:
Jamil Lambert, PhD 2024-11-18 10:24:20 +00:00
parent dbedac1bff
commit fe10ff2eb7
No known key found for this signature in database
GPG Key ID: 54DC29234AB5D2C0
2 changed files with 91 additions and 26 deletions

View File

@ -217,27 +217,45 @@ impl SignedAmount {
/// Consider using `unsigned_abs` which is often more practical. /// Consider using `unsigned_abs` which is often more practical.
/// ///
/// Returns [`None`] if overflow occurred. (`self == MIN`) /// Returns [`None`] if overflow occurred. (`self == MIN`)
pub fn checked_abs(self) -> Option<SignedAmount> { self.0.checked_abs().map(SignedAmount) } pub const fn checked_abs(self) -> Option<SignedAmount> {
// No `map()` in const context.
match self.0.checked_abs() {
Some(res) => Some(SignedAmount(res)),
None => None,
}
}
/// Checked addition. /// Checked addition.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_add(self, rhs: SignedAmount) -> Option<SignedAmount> { pub const fn checked_add(self, rhs: SignedAmount) -> Option<SignedAmount> {
self.0.checked_add(rhs.0).map(SignedAmount) // No `map()` in const context.
match self.0.checked_add(rhs.0) {
Some(res) => Some(SignedAmount(res)),
None => None,
}
} }
/// Checked subtraction. /// Checked subtraction.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_sub(self, rhs: SignedAmount) -> Option<SignedAmount> { pub const fn checked_sub(self, rhs: SignedAmount) -> Option<SignedAmount> {
self.0.checked_sub(rhs.0).map(SignedAmount) // No `map()` in const context.
match self.0.checked_sub(rhs.0) {
Some(res) => Some(SignedAmount(res)),
None => None,
}
} }
/// Checked multiplication. /// Checked multiplication.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_mul(self, rhs: i64) -> Option<SignedAmount> { pub const fn checked_mul(self, rhs: i64) -> Option<SignedAmount> {
self.0.checked_mul(rhs).map(SignedAmount) // No `map()` in const context.
match self.0.checked_mul(rhs) {
Some(res) => Some(SignedAmount(res)),
None => None,
}
} }
/// Checked integer division. /// Checked integer division.
@ -245,15 +263,23 @@ impl SignedAmount {
/// Be aware that integer division loses the remainder if no exact division can be made. /// Be aware that integer division loses the remainder if no exact division can be made.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_div(self, rhs: i64) -> Option<SignedAmount> { pub const fn checked_div(self, rhs: i64) -> Option<SignedAmount> {
self.0.checked_div(rhs).map(SignedAmount) // No `map()` in const context.
match self.0.checked_div(rhs) {
Some(res) => Some(SignedAmount(res)),
None => None,
}
} }
/// Checked remainder. /// Checked remainder.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_rem(self, rhs: i64) -> Option<SignedAmount> { pub const fn checked_rem(self, rhs: i64) -> Option<SignedAmount> {
self.0.checked_rem(rhs).map(SignedAmount) // No `map()` in const context.
match self.0.checked_rem(rhs) {
Some(res) => Some(SignedAmount(res)),
None => None,
}
} }
/// Unchecked addition. /// Unchecked addition.

View File

@ -196,28 +196,48 @@ impl Amount {
/// Checked addition. /// Checked addition.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_add(self, rhs: Amount) -> Option<Amount> { pub const fn checked_add(self, rhs: Amount) -> Option<Amount> {
self.0.checked_add(rhs.0).map(Amount) // No `map()` in const context.
match self.0.checked_add(rhs.0) {
Some(res) => Some(Amount(res)),
None => None,
}
} }
/// Checked subtraction. /// Checked subtraction.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_sub(self, rhs: Amount) -> Option<Amount> { pub const fn checked_sub(self, rhs: Amount) -> Option<Amount> {
self.0.checked_sub(rhs.0).map(Amount) // No `map()` in const context.
match self.0.checked_sub(rhs.0) {
Some(res) => Some(Amount(res)),
None => None,
}
} }
/// Checked multiplication. /// Checked multiplication.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_mul(self, rhs: u64) -> Option<Amount> { self.0.checked_mul(rhs).map(Amount) } pub const fn checked_mul(self, rhs: u64) -> Option<Amount> {
// No `map()` in const context.
match self.0.checked_mul(rhs) {
Some(res) => Some(Amount(res)),
None => None,
}
}
/// Checked integer division. /// Checked integer division.
/// ///
/// Be aware that integer division loses the remainder if no exact division can be made. /// Be aware that integer division loses the remainder if no exact division can be made.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_div(self, rhs: u64) -> Option<Amount> { self.0.checked_div(rhs).map(Amount) } pub const fn checked_div(self, rhs: u64) -> Option<Amount> {
// No `map()` in const context.
match self.0.checked_div(rhs) {
Some(res) => Some(Amount(res)),
None => None,
}
}
/// Checked weight ceiling division. /// Checked weight ceiling division.
/// ///
@ -227,12 +247,19 @@ impl Amount {
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub fn checked_div_by_weight_ceil(self, rhs: Weight) -> Option<FeeRate> { pub const fn checked_div_by_weight_ceil(self, rhs: Weight) -> Option<FeeRate> {
let sats = self.0.checked_mul(1_000)?;
let wu = rhs.to_wu(); let wu = rhs.to_wu();
// No `?` operator in const context.
let fee_rate = sats.checked_add(wu.checked_sub(1)?)?.checked_div(wu)?; if let Some(sats) = self.0.checked_mul(1_000) {
Some(FeeRate::from_sat_per_kwu(fee_rate)) if let Some(wu_minus_one) = wu.checked_sub(1) {
if let Some(sats_plus_wu_minus_one) = sats.checked_add(wu_minus_one) {
if let Some(fee_rate) = sats_plus_wu_minus_one.checked_div(wu) {
return Some(FeeRate::from_sat_per_kwu(fee_rate));
}
}
}
}
None
} }
/// Checked weight floor division. /// Checked weight floor division.
@ -242,15 +269,27 @@ impl Amount {
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub fn checked_div_by_weight_floor(self, rhs: Weight) -> Option<FeeRate> { pub const fn checked_div_by_weight_floor(self, rhs: Weight) -> Option<FeeRate> {
let fee_rate = self.0.checked_mul(1_000)?.checked_div(rhs.to_wu())?; // No `?` operator in const context.
Some(FeeRate::from_sat_per_kwu(fee_rate)) match self.0.checked_mul(1_000) {
Some(res) => match res.checked_div(rhs.to_wu()) {
Some(fee_rate) => Some(FeeRate::from_sat_per_kwu(fee_rate)),
None => None,
},
None => None,
}
} }
/// Checked remainder. /// Checked remainder.
/// ///
/// Returns [`None`] if overflow occurred. /// Returns [`None`] if overflow occurred.
pub fn checked_rem(self, rhs: u64) -> Option<Amount> { self.0.checked_rem(rhs).map(Amount) } pub const fn checked_rem(self, rhs: u64) -> Option<Amount> {
// No `map()` in const context.
match self.0.checked_rem(rhs) {
Some(res) => Some(Amount(res)),
None => None,
}
}
/// Unchecked addition. /// Unchecked addition.
/// ///