From 1c46541452aa14ae7ebea06a27e87cadea3dc1ea Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 29 Mar 2023 19:28:14 -0400 Subject: [PATCH] Plug baseXX into Address. --- network-hypervisor/src/vl1/address.rs | 35 ++++++++++++++++++++++----- utils/src/base24.rs | 7 +++++- utils/src/base62.rs | 6 +++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/network-hypervisor/src/vl1/address.rs b/network-hypervisor/src/vl1/address.rs index e72ec5f9d..2c1caf6bd 100644 --- a/network-hypervisor/src/vl1/address.rs +++ b/network-hypervisor/src/vl1/address.rs @@ -9,10 +9,8 @@ use std::str::FromStr; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use zerotier_utils::base24; use zerotier_utils::error::InvalidParameterError; -use zerotier_utils::hex; -use zerotier_utils::memory; +use zerotier_utils::{base24, base62, hex, memory}; /// A full (V2) ZeroTier address. /// @@ -102,7 +100,17 @@ impl Borrow<[u8; Self::SIZE_BYTES]> for Address { impl ToString for Address { #[inline(always)] fn to_string(&self) -> String { - base24::encode(&self.0) + let mut s = String::with_capacity(48 * 2); + base24::encode_into(&self.0[..4], &mut s); + s.push('-'); + base24::encode_into(&self.0[4..8], &mut s); + s.push('-'); + base24::encode_into(&self.0[8..12], &mut s); + s.push('-'); + base24::encode_into(&self.0[12..16], &mut s); + s.push('-'); + base62::encode_into(&self.0[16..], &mut s, 43); + s } } @@ -111,7 +119,19 @@ impl FromStr for Address { #[inline] fn from_str(s: &str) -> Result { - base24::decode(s.as_bytes()).and_then(|b| Self::from_bytes(b.as_slice())) + let mut a = Self([0u8; Self::SIZE_BYTES]); + let mut f = 0; + for ss in s.split('-') { + if f <= 3 { + base24::decode_into_slice(ss.as_bytes(), &mut a.0[f * 4..(f + 1) * 4])?; + } else if f == 4 { + base62::decode_into_slice(ss.as_bytes(), &mut a.0[16..]).map_err(|_| InvalidParameterError("invalid base62"))?; + } else { + return Err(InvalidParameterError("too many sections")); + } + f += 1; + } + return Ok(a); } } @@ -488,7 +508,10 @@ mod tests { for _ in 0..64 { let mut tmp = Address::new_uninitialized(); random::fill_bytes_secure(&mut tmp.0); - println!("{}", tmp.to_string()); + let s = tmp.to_string(); + println!("{}", s); + let tmp2 = Address::from_str(s.as_str()).unwrap(); + assert!(tmp == tmp2); } } } diff --git a/utils/src/base24.rs b/utils/src/base24.rs index b61bf6bf8..251482572 100644 --- a/utils/src/base24.rs +++ b/utils/src/base24.rs @@ -66,7 +66,7 @@ fn decode_up_to_u32(s: &[u8]) -> Result { } /// Decode a base24 ASCII slice into bytes (no padding, length determines output length) -pub fn decode_into(s: &[u8], b: &mut Vec) -> Result<(), InvalidParameterError> { +pub fn decode_into(s: &[u8], b: &mut W) -> Result<(), InvalidParameterError> { let mut s = s.as_ref(); while s.len() >= 7 { @@ -88,6 +88,11 @@ pub fn decode_into(s: &[u8], b: &mut Vec) -> Result<(), InvalidParameterErro return Ok(()); } +#[inline] +pub fn decode_into_slice(s: &[u8], mut b: &mut [u8]) -> Result<(), InvalidParameterError> { + decode_into(s, &mut b) +} + pub fn encode(b: &[u8]) -> String { let mut tmp = String::with_capacity(((b.len() / 4) * 7) + 2); encode_into(b, &mut tmp); diff --git a/utils/src/base62.rs b/utils/src/base62.rs index 4c48fc847..98ca7204e 100644 --- a/utils/src/base62.rs +++ b/utils/src/base62.rs @@ -85,6 +85,12 @@ pub fn decode_into(s: &[u8], b: &mut W, output_length: usize) -> std:: return Ok(()); } +#[inline] +pub fn decode_into_slice(s: &[u8], mut b: &mut [u8]) -> std::io::Result<()> { + let l = b.len(); + decode_into(s, &mut b, l) +} + /// Decode into and return an array whose length is the desired output_length. /// None is returned if there is an error. #[inline]