object.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 Bech32Object<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send>: 24 From<T> 25 + Deref<Target = T> 26 + Clone 27 + Debug 28 + Display 29 + ToBytes 30 + FromBytes 31 + PartialEq 32 + Eq 33 + Serialize 34 + DeserializeOwned 35 + Sync 36 + Send 37 { 38 fn prefix() -> String; 39 } 40 41 /// Converts a string of 4 characters into a `u32` for a human-readable prefix in Bech32. 42 #[macro_export] 43 macro_rules! hrp4 { 44 ( $persona: expr ) => {{ 45 $crate::const_assert!($persona.len() == 4); 46 let p = $persona.as_bytes(); 47 u32::from_le_bytes([p[0], p[1], p[2], p[3]]) 48 }}; 49 } 50 51 #[derive(Clone, PartialEq, Eq, Hash)] 52 pub struct AlphaObject<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32>(T); 53 54 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Bech32Object<T> 55 for AlphaObject<T, PREFIX> 56 { 57 #[inline] 58 fn prefix() -> String { 59 String::from_utf8(PREFIX.to_le_bytes().to_vec()).expect("Failed to convert prefix to string") 60 } 61 } 62 63 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> From<T> 64 for AlphaObject<T, PREFIX> 65 { 66 #[inline] 67 fn from(data: T) -> Self { 68 Self(data) 69 } 70 } 71 72 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromBytes 73 for AlphaObject<T, PREFIX> 74 { 75 /// Reads data into a buffer. 76 #[inline] 77 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 78 Ok(Self(FromBytes::read_le(&mut reader)?)) 79 } 80 } 81 82 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> ToBytes 83 for AlphaObject<T, PREFIX> 84 { 85 /// Writes the data to a buffer. 86 #[inline] 87 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 88 self.0.write_le(&mut writer) 89 } 90 } 91 92 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromStr 93 for AlphaObject<T, PREFIX> 94 { 95 type Err = Error; 96 97 /// Reads in a bech32m string. 98 #[inline] 99 fn from_str(string: &str) -> Result<Self, Self::Err> { 100 let (hrp, data, variant) = bech32::decode(string)?; 101 if hrp.as_bytes() != PREFIX.to_le_bytes() { 102 bail!("Invalid prefix for a bech32m hash: {hrp}") 103 }; 104 if data.is_empty() { 105 bail!("Bech32m hash data is empty") 106 } 107 if variant != bech32::Variant::Bech32m { 108 bail!("Hash is not a bech32m hash") 109 } 110 Ok(Self::read_le(&*Vec::from_base32(&data)?)?) 111 } 112 } 113 114 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Display 115 for AlphaObject<T, PREFIX> 116 { 117 #[inline] 118 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 119 bech32::encode_to_fmt( 120 f, 121 &Self::prefix(), 122 self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(), 123 bech32::Variant::Bech32m, 124 ) 125 .expect("Failed to encode in bech32m") 126 } 127 } 128 129 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Debug 130 for AlphaObject<T, PREFIX> 131 { 132 #[inline] 133 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 134 write!(f, "AlphaObject {{ hrp: {:?}, data: {:?} }}", &Self::prefix(), self.0) 135 } 136 } 137 138 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Serialize 139 for AlphaObject<T, PREFIX> 140 { 141 #[inline] 142 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 143 match serializer.is_human_readable() { 144 true => serializer.collect_str(self), 145 false => ToBytesSerializer::serialize_with_size_encoding(self, serializer), 146 } 147 } 148 } 149 150 impl<'de, T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deserialize<'de> 151 for AlphaObject<T, PREFIX> 152 { 153 #[inline] 154 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 155 match deserializer.is_human_readable() { 156 true => FromStr::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom), 157 false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, &Self::prefix()), 158 } 159 } 160 } 161 162 impl<T: Default + Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Default 163 for AlphaObject<T, PREFIX> 164 { 165 fn default() -> Self { 166 Self(T::default()) 167 } 168 } 169 170 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deref 171 for AlphaObject<T, PREFIX> 172 { 173 type Target = T; 174 175 #[inline] 176 fn deref(&self) -> &Self::Target { 177 &self.0 178 } 179 } 180 181 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Borrow<T> 182 for AlphaObject<T, PREFIX> 183 { 184 #[inline] 185 fn borrow(&self) -> &T { 186 &self.0 187 } 188 }