From cc72f032dca9a0a203bcc5da2892fc68c46c1420 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 3 Oct 2024 16:53:56 +0000 Subject: [PATCH] Marginally reduce allocations in `lightning-invoice` In aa2f6b47df312f026213d0ceaaff20ffe955c377 we refactored `lightning-invoice` de/serialization to use the new version of `bech32`, also reducing some trivial unnecessary allocations when we did so. Here we drop a few additional allocations which came up in review. --- lightning-invoice/src/de.rs | 2 +- lightning-invoice/src/ser.rs | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lightning-invoice/src/de.rs b/lightning-invoice/src/de.rs index 7c425441f..446fd5c71 100644 --- a/lightning-invoice/src/de.rs +++ b/lightning-invoice/src/de.rs @@ -712,7 +712,7 @@ impl FromBase32 for PrivateRoute { return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields); } - let mut route_hops = Vec::::new(); + let mut route_hops = Vec::with_capacity(bytes.len() / 51); let mut bytes = bytes.as_slice(); while !bytes.is_empty() { diff --git a/lightning-invoice/src/ser.rs b/lightning-invoice/src/ser.rs index 4000241f5..3d79a2533 100644 --- a/lightning-invoice/src/ser.rs +++ b/lightning-invoice/src/ser.rs @@ -218,19 +218,20 @@ impl Display for SiPrefix { } /// Encode an integer to base32, big endian, without leading zeros -fn encode_int_be_base32(int: u64) -> Vec { +fn encode_int_be_base32(int: u64) -> impl ExactSizeIterator { let base = 32u64; // (64 + 4) / 5 == 13 - let mut out_vec = Vec::::with_capacity(13); + let mut out = [Fe32::Q; 13]; + let mut out_pos = 0; let mut rem_int = int; while rem_int != 0 { - out_vec.push(Fe32::try_from((rem_int % base) as u8).expect("always <32")); + out[out_pos] = Fe32::try_from((rem_int % base) as u8).expect("always <32"); + out_pos += 1; rem_int /= base; } - out_vec.reverse(); - out_vec + out.into_iter().take(out_pos).rev() } /// The length of the output of `encode_int_be_base32`. @@ -252,7 +253,7 @@ impl Base32Iterable for PositiveTimestamp { let fes = encode_int_be_base32(self.as_unix_timestamp()); debug_assert!(fes.len() <= 7, "Invalid timestamp length"); let to_pad = 7 - fes.len(); - Box::new(core::iter::repeat(Fe32::Q).take(to_pad).chain(fes.into_iter())) + Box::new(core::iter::repeat(Fe32::Q).take(to_pad).chain(fes)) } } @@ -305,7 +306,7 @@ impl Base32Len for PayeePubKey { impl Base32Iterable for ExpiryTime { fn fe_iter<'s>(&'s self) -> Box + 's> { - Box::new(encode_int_be_base32(self.as_seconds()).into_iter()) + Box::new(encode_int_be_base32(self.as_seconds())) } } @@ -317,7 +318,7 @@ impl Base32Len for ExpiryTime { impl Base32Iterable for MinFinalCltvExpiryDelta { fn fe_iter<'s>(&'s self) -> Box + 's> { - Box::new(encode_int_be_base32(self.0).into_iter()) + Box::new(encode_int_be_base32(self.0)) } } @@ -504,6 +505,6 @@ mod test { .map(|v| Fe32::try_from(v).expect("<= 31")) .collect::>(); - assert_eq!(expected_out, encode_int_be_base32(input)); + assert_eq!(expected_out, encode_int_be_base32(input).collect::>()); } } -- 2.39.5