Skip to content

Commit 7dc66e3

Browse files
committed
impl LowerHex, UpperHex, Octal, and Binary for ChildNumber
Each trait forwards to the inner u32 index and formatting done based on the variant used with the alternate path See discussion: rust-bitcoin#4620 (comment)
1 parent f034367 commit 7dc66e3

File tree

1 file changed

+96
-8
lines changed

1 file changed

+96
-8
lines changed

bitcoin/src/bip32.rs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,29 @@ impl ChildNumber {
193193
ChildNumber::Hardened { index: idx } => ChildNumber::from_hardened_idx(idx + 1),
194194
}
195195
}
196+
197+
/// Formats the child number using the provided formatting function.
198+
///
199+
/// For hardened child numbers appends a `'` or `hardened_alt_suffix`
200+
/// depending on the formatter.
201+
fn format_with<F>(
202+
&self,
203+
f: &mut fmt::Formatter,
204+
format_fn: F,
205+
hardened_alt_suffix: &str,
206+
) -> fmt::Result
207+
where
208+
F: Fn(&u32, &mut fmt::Formatter) -> fmt::Result,
209+
{
210+
match *self {
211+
ChildNumber::Hardened { index } => {
212+
format_fn(&index, f)?;
213+
let alt = f.alternate();
214+
f.write_str(if alt { hardened_alt_suffix } else { "'" })
215+
}
216+
ChildNumber::Normal { index } => format_fn(&index, f),
217+
}
218+
}
196219
}
197220

198221
impl From<u32> for ChildNumber {
@@ -216,14 +239,31 @@ impl From<ChildNumber> for u32 {
216239

217240
impl fmt::Display for ChildNumber {
218241
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219-
match *self {
220-
ChildNumber::Hardened { index } => {
221-
fmt::Display::fmt(&index, f)?;
222-
let alt = f.alternate();
223-
f.write_str(if alt { "h" } else { "'" })
224-
}
225-
ChildNumber::Normal { index } => fmt::Display::fmt(&index, f),
226-
}
242+
self.format_with(f, fmt::Display::fmt, "h")
243+
}
244+
}
245+
246+
impl fmt::LowerHex for ChildNumber {
247+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248+
self.format_with(f, fmt::LowerHex::fmt, "h")
249+
}
250+
}
251+
252+
impl fmt::UpperHex for ChildNumber {
253+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
254+
self.format_with(f, fmt::UpperHex::fmt, "H")
255+
}
256+
}
257+
258+
impl fmt::Octal for ChildNumber {
259+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260+
self.format_with(f, fmt::Octal::fmt, "h")
261+
}
262+
}
263+
264+
impl fmt::Binary for ChildNumber {
265+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266+
self.format_with(f, fmt::Binary::fmt, "h")
227267
}
228268
}
229269

@@ -1123,6 +1163,54 @@ mod tests {
11231163
assert_eq!(format!("{:#}", path), "84h/0h/0h/0/0");
11241164
}
11251165

1166+
#[test]
1167+
fn test_lowerhex_formatting() {
1168+
let normal = Normal { index: 42 };
1169+
let hardened = Hardened { index: 42 };
1170+
1171+
assert_eq!(format!("{:x}", normal), "2a");
1172+
assert_eq!(format!("{:#x}", normal), "0x2a");
1173+
1174+
assert_eq!(format!("{:x}", hardened), "2a'");
1175+
assert_eq!(format!("{:#x}", hardened), "0x2ah");
1176+
}
1177+
1178+
#[test]
1179+
fn test_upperhex_formatting() {
1180+
let normal = Normal { index: 42 };
1181+
let hardened = Hardened { index: 42 };
1182+
1183+
assert_eq!(format!("{:X}", normal), "2A");
1184+
assert_eq!(format!("{:#X}", normal), "0x2A");
1185+
1186+
assert_eq!(format!("{:X}", hardened), "2A'");
1187+
assert_eq!(format!("{:#X}", hardened), "0x2AH");
1188+
}
1189+
1190+
#[test]
1191+
fn test_octal_formatting() {
1192+
let normal = Normal { index: 42 };
1193+
let hardened = Hardened { index: 42 };
1194+
1195+
assert_eq!(format!("{:o}", normal), "52");
1196+
assert_eq!(format!("{:#o}", normal), "0o52");
1197+
1198+
assert_eq!(format!("{:o}", hardened), "52'");
1199+
assert_eq!(format!("{:#o}", hardened), "0o52h");
1200+
}
1201+
1202+
#[test]
1203+
fn test_binary_formatting() {
1204+
let normal = Normal { index: 42 };
1205+
let hardened = Hardened { index: 42 };
1206+
1207+
assert_eq!(format!("{:b}", normal), "101010");
1208+
assert_eq!(format!("{:#b}", normal), "0b101010");
1209+
1210+
assert_eq!(format!("{:b}", hardened), "101010'");
1211+
assert_eq!(format!("{:#b}", hardened), "0b101010h");
1212+
}
1213+
11261214
#[test]
11271215
fn parse_derivation_path_out_of_range() {
11281216
let invalid_path = "2147483648";

0 commit comments

Comments
 (0)