This code seems more complex than it needs to be:
pub fn new(id_bytes: [u8; 32], ipv4: Ipv4Addr, port: u16) -> Result<RemotePeer, secp256k1::Error> {
let serialised_pkey: Vec<u8> = [0x02].iter().chain(id_bytes.iter()).map(|x| *x).collect();
Ok(RemotePeer {
id: U256::from_le_bytes(id_bytes),
pkey: PublicKey::from_slice(&serialised_pkey)?,
ipv4,
port
})
}
I have the final 32 bytes of a public key, and I need to prepend it with an '0x02' before creating the public key.
Is there a better alternative to:
[0x02].iter().chain(id_bytes.iter()).map(|x| *x).collect();
I particularly dislike the .map()
which only exists to silence an error about &u8
and u8
not being the same.
First, .map(|x| *x)
has a shorter version: .copied()
. However, there's ways to avoid the iterator entirely.
Since you know the length of the array to be 32, you can avoid allocating a Vec
by using an array of length 33.
let mut serialised_pkey = [0; 33];
serialised_pkey[0] = 0x02;
serialised_pkey[1..].copy_from_slice(&id_bytes);
If you didn't know the length, you could use Vec::extend_from_slice
.
let mut serialised_pkey = Vec::with_capacity(id_bytes.len() + 1);
serialised_pkey.push(0x02);
serialised_pkey.extend_from_slice(&id_bytes);
If you had control over PublicKey
, you could write a constructor that takes an implementer of Read
. This is more flexible since it doesn't require all the bytes to be in one slice. Consider using the Read
and Write
traits when dealing with sequences of u8
.
use std::io::Cursor;
let serialised_pkey = Cursor::new([0x02]).chain(Cursor::new(id_bytes));
let public_key = PublicKey::from_reader(serialised_pkey)?;