Merge rust-bitcoin/rust-bitcoin#3227: feat: remove zeroed vector by pushing front

441aac0a08 fix: vec! macro enabled only for test module (Chris Hyunhum Cho)
a050618fd8 feat: remove zeroed vector by pushing front (Chris Hyunhum Cho)

Pull request description:

  Remove useless zeroed vector following https://github.com/rust-bitcoin/rust-bitcoin/issues/3131.
  1. Init vector with capacity not to realloc when pushing.
  2. If vector is empty(the first iteration), push data from the front.
  3. Iterate vector from the front, and copy it from the end.

ACKs for top commit:
  apoelstra:
    ACK 441aac0a08 successfully ran local tests
  jamillambert:
    ACK 441aac0a08
  Kixunil:
    ACK 441aac0a08

Tree-SHA512: dee934f675786e6977216de9516ecb7f03fa17304891f060b33d46ff3a02342b817628b68dc429c65730a52e1d99c3d0d5e9d47afee5b727b06d3c800767369e
This commit is contained in:
merge-script 2024-08-26 21:53:14 +00:00
commit d7ac6af5b4
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
1 changed files with 14 additions and 7 deletions

View File

@ -18,7 +18,6 @@
#![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.
#[macro_use]
extern crate alloc; extern crate alloc;
#[cfg(bench)] #[cfg(bench)]
@ -69,7 +68,7 @@ static BASE58_DIGITS: [Option<u8>; 128] = [
/// Decodes a base58-encoded string into a byte vector. /// Decodes a base58-encoded string into a byte vector.
pub fn decode(data: &str) -> Result<Vec<u8>, InvalidCharacterError> { pub fn decode(data: &str) -> Result<Vec<u8>, InvalidCharacterError> {
// 11/15 is just over log_256(58) // 11/15 is just over log_256(58)
let mut scratch = vec![0u8; 1 + data.len() * 11 / 15]; let mut scratch = Vec::with_capacity(1 + data.len() * 11 / 15);
// Build in base 256 // Build in base 256
for d58 in data.bytes() { for d58 in data.bytes() {
// Compute "X = X * 58 + next_digit" in base 256 // Compute "X = X * 58 + next_digit" in base 256
@ -82,10 +81,17 @@ pub fn decode(data: &str) -> Result<Vec<u8>, InvalidCharacterError> {
return Err(InvalidCharacterError { invalid: d58 }); return Err(InvalidCharacterError { invalid: d58 });
} }
}; };
for d256 in scratch.iter_mut().rev() { if scratch.is_empty() {
carry += u32::from(*d256) * 58; for _ in 0..scratch.capacity() {
*d256 = carry as u8; // cast loses data intentionally scratch.push(carry as u8);
carry /= 256; carry /= 256;
}
} else {
for d256 in scratch.iter_mut() {
carry += u32::from(*d256) * 58;
*d256 = carry as u8; // cast loses data intentionally
carry /= 256;
}
} }
assert_eq!(carry, 0); assert_eq!(carry, 0);
} }
@ -93,7 +99,7 @@ pub fn decode(data: &str) -> Result<Vec<u8>, InvalidCharacterError> {
// Copy leading zeroes directly // Copy leading zeroes directly
let mut ret: Vec<u8> = data.bytes().take_while(|&x| x == BASE58_CHARS[0]).map(|_| 0).collect(); let mut ret: Vec<u8> = data.bytes().take_while(|&x| x == BASE58_CHARS[0]).map(|_| 0).collect();
// Copy rest of string // Copy rest of string
ret.extend(scratch.into_iter().skip_while(|&x| x == 0)); ret.extend(scratch.into_iter().rev().skip_while(|&x| x == 0));
Ok(ret) Ok(ret)
} }
@ -241,6 +247,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use alloc::vec;
use hex::test_hex_unwrap as hex; use hex::test_hex_unwrap as hex;
use super::*; use super::*;