id.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use crate::prelude::*; 17 18 use anyhow::Result; 19 use bech32::{self, FromBase32, ToBase32}; 20 use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; 21 use std::borrow::Borrow; 22 23 pub trait Bech32ID<F: FieldTrait>: 24 From<F> 25 + Deref<Target = F> 26 + Into<Vec<F>> 27 + Uniform 28 + Copy 29 + Clone 30 + Default 31 + Debug 32 + Display 33 + FromStr 34 + ToBytes 35 + FromBytes 36 + Serialize 37 + DeserializeOwned 38 + PartialEq 39 + Eq 40 + core::hash::Hash 41 + Sync 42 + Send 43 { 44 fn prefix() -> String; 45 fn size_in_bytes() -> usize; 46 fn number_of_data_characters() -> usize; 47 } 48 49 #[rustfmt::skip] 50 #[macro_export] 51 macro_rules! const_assert { 52 ($x:expr $(,)*) => { 53 pub const ASSERT: [(); 1] = [()]; 54 pub const fn bool_assert(x: bool) -> bool { x } 55 let _ = ASSERT[!bool_assert($x) as usize]; 56 }; 57 } 58 59 /// Converts a string of 2 characters into a `u16` for a human-readable prefix in Bech32. 60 #[macro_export] 61 macro_rules! hrp2 { 62 ( $persona: expr ) => {{ 63 const_assert!($persona.len() == 2); 64 let p = $persona.as_bytes(); 65 u16::from_le_bytes([p[0], p[1]]) 66 }}; 67 } 68 69 #[derive(Copy, Clone, PartialEq, Eq, Hash)] 70 pub struct AlphaID<F: FieldTrait, const PREFIX: u16>(F); 71 72 impl<F: FieldTrait, const PREFIX: u16> Bech32ID<F> for AlphaID<F, PREFIX> { 73 #[inline] 74 fn prefix() -> String { 75 String::from_utf8(PREFIX.to_le_bytes().to_vec()).expect("Failed to convert prefix to string") 76 } 77 78 #[inline] 79 fn size_in_bytes() -> usize { 80 F::size_in_bits().div_ceil(8) 81 } 82 83 #[inline] 84 fn number_of_data_characters() -> usize { 85 (Self::size_in_bytes() * 8).div_ceil(5) 86 } 87 } 88 89 impl<F: FieldTrait, const PREFIX: u16> From<F> for AlphaID<F, PREFIX> { 90 #[inline] 91 fn from(data: F) -> Self { 92 Self(data) 93 } 94 } 95 96 impl<F: FieldTrait, const PREFIX: u16> Default for AlphaID<F, PREFIX> { 97 #[inline] 98 fn default() -> Self { 99 Self(F::zero()) 100 } 101 } 102 103 impl<F: FieldTrait, const PREFIX: u16> FromBytes for AlphaID<F, PREFIX> { 104 /// Reads data into a buffer. 105 #[inline] 106 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 107 Ok(Self(F::read_le(&mut reader)?)) 108 } 109 } 110 111 impl<F: FieldTrait, const PREFIX: u16> ToBytes for AlphaID<F, PREFIX> { 112 /// Writes the data to a buffer. 113 #[inline] 114 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 115 self.0.write_le(&mut writer) 116 } 117 } 118 119 impl<F: FieldTrait, const PREFIX: u16> FromStr for AlphaID<F, PREFIX> { 120 type Err = Error; 121 122 /// Reads in a bech32m string. 123 #[inline] 124 fn from_str(string: &str) -> Result<Self, Self::Err> { 125 const CHECKSUM_STRING_LENGTH: usize = 6; 126 if string.len() != 3 + Self::number_of_data_characters() + CHECKSUM_STRING_LENGTH { 127 bail!("Invalid byte size for a bech32m hash: {} bytes", string.len()) 128 } 129 130 let (hrp, data, variant) = bech32::decode(string)?; 131 if hrp.as_bytes() != PREFIX.to_le_bytes() { 132 bail!("Invalid prefix for a bech32m hash: {hrp}") 133 }; 134 if data.is_empty() { 135 bail!("Bech32m hash data is empty") 136 } 137 if variant != bech32::Variant::Bech32m { 138 bail!("Hash is not a bech32m hash") 139 } 140 Ok(Self::read_le(&*Vec::from_base32(&data)?)?) 141 } 142 } 143 144 impl<F: FieldTrait, const PREFIX: u16> Display for AlphaID<F, PREFIX> { 145 #[inline] 146 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 147 bech32::encode_to_fmt( 148 f, 149 &Self::prefix(), 150 self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(), 151 bech32::Variant::Bech32m, 152 ) 153 .expect("Failed to encode in bech32m") 154 } 155 } 156 157 impl<F: FieldTrait, const PREFIX: u16> Debug for AlphaID<F, PREFIX> { 158 #[inline] 159 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 160 write!(f, "AlphaLocator {{ hrp: {:?}, data: {:?} }}", &Self::prefix(), self.0) 161 } 162 } 163 164 impl<F: FieldTrait, const PREFIX: u16> Serialize for AlphaID<F, PREFIX> { 165 #[inline] 166 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 167 match serializer.is_human_readable() { 168 true => serializer.collect_str(self), 169 false => ToBytesSerializer::serialize(self, serializer), 170 } 171 } 172 } 173 174 impl<'de, F: FieldTrait, const PREFIX: u16> Deserialize<'de> for AlphaID<F, PREFIX> { 175 #[inline] 176 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 177 match deserializer.is_human_readable() { 178 true => FromStr::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom), 179 false => FromBytesDeserializer::<Self>::deserialize(deserializer, &Self::prefix(), Self::size_in_bytes()), 180 } 181 } 182 } 183 184 impl<F: FieldTrait, const PREFIX: u16> Deref for AlphaID<F, PREFIX> { 185 type Target = F; 186 187 #[inline] 188 fn deref(&self) -> &Self::Target { 189 &self.0 190 } 191 } 192 193 impl<F: FieldTrait, const PREFIX: u16> Borrow<F> for AlphaID<F, PREFIX> { 194 #[inline] 195 fn borrow(&self) -> &F { 196 &self.0 197 } 198 } 199 200 #[allow(clippy::from_over_into)] 201 impl<F: FieldTrait, const PREFIX: u16> Into<Vec<F>> for AlphaID<F, PREFIX> { 202 #[inline] 203 fn into(self) -> Vec<F> { 204 vec![self.0] 205 } 206 } 207 208 impl<F: FieldTrait, const PREFIX: u16> Distribution<AlphaID<F, PREFIX>> for Standard { 209 #[inline] 210 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> AlphaID<F, PREFIX> { 211 AlphaID::<F, PREFIX>(Uniform::rand(rng)) 212 } 213 }