diff --git a/units/src/amount.rs b/units/src/amount.rs index 94cfaca3e9..fe2717103b 100644 --- a/units/src/amount.rs +++ b/units/src/amount.rs @@ -670,7 +670,7 @@ fn split_amount_and_denomination(s: &str) -> Result<(&str, Denomination), ParseE } /// Options given by `fmt::Formatter` -struct FormatOptions { +pub struct FormatOptions { fill: char, align: Option, width: Option, @@ -821,9 +821,17 @@ fn fmt_satoshi_in( if total_decimals > 0 { write!(f, ".")?; } - if norm_nb_decimals > 0 { + + if let Some(f_precision) = options.precision { + if f_precision < norm_nb_decimals && norm_nb_decimals > 0 { + write!(f, "{:0width$}", 0, width = f_precision)?; + } else if norm_nb_decimals > 0 { + write!(f, "{:0width$}", num_after_decimal_point, width = norm_nb_decimals)?; + } + } else if norm_nb_decimals > 0 { write!(f, "{:0width$}", num_after_decimal_point, width = norm_nb_decimals)?; } + repeat_char(f, '0', trailing_decimal_zeros)?; if show_denom { @@ -1349,8 +1357,8 @@ impl SignedAmount { /// /// Does not include the denomination. #[rustfmt::skip] - pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result { - fmt_satoshi_in(self.unsigned_abs().to_sat(), self.is_negative(), f, denom, false, FormatOptions::default()) + pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination, options: FormatOptions) -> fmt::Result { + fmt_satoshi_in(self.unsigned_abs().to_sat(), self.is_negative(), f, denom, false, options) } /// Get a string number of this [SignedAmount] in the given denomination. @@ -1359,7 +1367,7 @@ impl SignedAmount { #[cfg(feature = "alloc")] pub fn to_string_in(self, denom: Denomination) -> String { let mut buf = String::new(); - self.fmt_value_in(&mut buf, denom).unwrap(); + self.fmt_value_in(&mut buf, denom, FormatOptions::default()).unwrap(); buf } @@ -1368,7 +1376,7 @@ impl SignedAmount { #[cfg(feature = "alloc")] pub fn to_string_with_denomination(self, denom: Denomination) -> String { let mut buf = String::new(); - self.fmt_value_in(&mut buf, denom).unwrap(); + self.fmt_value_in(&mut buf, denom, FormatOptions::default()).unwrap(); write!(buf, " {}", denom).unwrap(); buf } @@ -1476,7 +1484,10 @@ impl fmt::Debug for SignedAmount { // Just using Bitcoin denominated string. impl fmt::Display for SignedAmount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.fmt_value_in(f, Denomination::Bitcoin)?; + let mut format_options = FormatOptions::default(); + format_options.precision.replace(f.precision().unwrap_or(8)); + self.fmt_value_in(f, Denomination::Bitcoin, format_options)?; + write!(f, " {}", Denomination::Bitcoin) } } @@ -2415,10 +2426,10 @@ mod tests { btc_check_fmt_non_negative_6, 1, "{}", "0.00000001"; btc_check_fmt_non_negative_7, 1, "{:2}", "0.00000001"; btc_check_fmt_non_negative_8, 1, "{:02}", "0.00000001"; - btc_check_fmt_non_negative_9, 1, "{:.1}", "0.00000001"; + btc_check_fmt_non_negative_9, 1, "{:.1}", "0.0"; btc_check_fmt_non_negative_10, 1, "{:11}", " 0.00000001"; - btc_check_fmt_non_negative_11, 1, "{:11.1}", " 0.00000001"; - btc_check_fmt_non_negative_12, 1, "{:011.1}", "00.00000001"; + btc_check_fmt_non_negative_11, 1, "{:11.1}", " 0.0"; + btc_check_fmt_non_negative_12, 1, "{:011.1}", "00.0"; btc_check_fmt_non_negative_13, 1, "{:.9}", "0.000000010"; btc_check_fmt_non_negative_14, 1, "{:11.9}", "0.000000010"; btc_check_fmt_non_negative_15, 1, "{:011.9}", "0.000000010"; @@ -2433,7 +2444,7 @@ mod tests { btc_check_fmt_non_negative_24, 110_000_000, "{}", "1.1"; btc_check_fmt_non_negative_25, 100_000_001, "{}", "1.00000001"; btc_check_fmt_non_negative_26, 100_000_001, "{:1}", "1.00000001"; - btc_check_fmt_non_negative_27, 100_000_001, "{:.1}", "1.00000001"; + btc_check_fmt_non_negative_27, 100_000_001, "{:.1}", "1.0"; btc_check_fmt_non_negative_28, 100_000_001, "{:10}", "1.00000001"; btc_check_fmt_non_negative_29, 100_000_001, "{:11}", " 1.00000001"; btc_check_fmt_non_negative_30, 100_000_001, "{:011}", "01.00000001"; @@ -2465,7 +2476,7 @@ mod tests { check_format_non_negative_show_denom! { Bitcoin, " BTC"; - btc_check_fmt_non_negative_show_denom_0, 1, "{:14.1}", "0.00000001"; + btc_check_fmt_non_negative_show_denom_0, 1, "{:14.1}", "0.0"; btc_check_fmt_non_negative_show_denom_1, 1, "{:14.8}", "0.00000001"; btc_check_fmt_non_negative_show_denom_2, 1, "{:15}", " 0.00000001"; btc_check_fmt_non_negative_show_denom_3, 1, "{:015}", "00.00000001"; @@ -2940,18 +2951,21 @@ mod tests { assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC"); assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC"); assert_eq!(format!("{}", Amount::from_sat(10)), "0.00000010 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(10)), "0.0000001 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(100)), "0.000001 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(1000)), "0.00001 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(10_000)), "0.0001 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(100_000)), "0.001 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(1_000_000)), "0.01 BTC"); - assert_eq!(format!("{:.2}", Amount::from_sat(10_000_000)), "0.10 BTC"); + assert_eq!(format!("{:.1}", Amount::from_sat(10)), "0.0 BTC"); + assert_eq!(format!("{:.2}", Amount::from_sat(10)), "0.00 BTC"); + assert_eq!(format!("{:.3}", Amount::from_sat(10)), "0.000 BTC"); + assert_eq!(format!("{:.4}", Amount::from_sat(10)), "0.0000 BTC"); + assert_eq!(format!("{:.5}", Amount::from_sat(10)), "0.00000 BTC"); + assert_eq!(format!("{:.6}", Amount::from_sat(10)), "0.000000 BTC"); + assert_eq!(format!("{:.7}", Amount::from_sat(10)), "0.0000001 BTC"); + assert_eq!(format!("{:.8}", Amount::from_sat(10)), "0.00000010 BTC"); + assert_eq!(format!("{:.9}", Amount::from_sat(10)), "0.000000100 BTC"); + assert_eq!(format!("{:.1}", Amount::from_sat(100_000_000)), "1.0 BTC"); assert_eq!(format!("{:.2}", Amount::from_sat(100_000_000)), "1.00 BTC"); assert_eq!(format!("{}", Amount::from_sat(100_000_000)), "1 BTC"); - assert_eq!(format!("{}", Amount::from_sat(40_000_000_000)), "400 BTC"); - assert_eq!(format!("{:.10}", Amount::from_sat(100_000_000)), "1.0000000000 BTC"); - assert_eq!(format!("{}", Amount::from_sat(400_000_000_000_010)), "4000000.00000010 BTC"); - assert_eq!(format!("{}", Amount::from_sat(400_000_000_000_000)), "4000000 BTC"); + assert_eq!(format!("{}", Amount::from_sat(40_000_000_001)), "400.00000001 BTC"); + assert_eq!(format!("{}", Amount::from_sat(40_000_000_010)), "400.00000010 BTC"); + assert_eq!(format!("{:.7}", Amount::from_sat(40_000_000_010)), "400.0000001 BTC"); + assert_eq!(format!("{:.1}", Amount::from_sat(40_000_000_001)), "400.0 BTC"); } }