object.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 use crate::prelude::*; 20 21 use anyhow::Result; 22 use bech32::{self, FromBase32, ToBase32}; 23 use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; 24 use std::borrow::Borrow; 25 26 pub trait Bech32Object<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send>: 27 From<T> 28 + Deref<Target = T> 29 + Clone 30 + Debug 31 + Display 32 + ToBytes 33 + FromBytes 34 + PartialEq 35 + Eq 36 + Serialize 37 + DeserializeOwned 38 + Sync 39 + Send 40 { 41 fn prefix() -> String; 42 } 43 44 /// Converts a string of 4 characters into a `u32` for a human-readable prefix in Bech32. 45 #[macro_export] 46 macro_rules! hrp4 { 47 ( $persona: expr ) => {{ 48 $crate::const_assert!($persona.len() == 4); 49 let p = $persona.as_bytes(); 50 u32::from_le_bytes([p[0], p[1], p[2], p[3]]) 51 }}; 52 } 53 54 #[derive(Clone, PartialEq, Eq, Hash)] 55 pub struct AlphaObject<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32>(T); 56 57 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Bech32Object<T> 58 for AlphaObject<T, PREFIX> 59 { 60 #[inline] 61 fn prefix() -> String { 62 String::from_utf8(PREFIX.to_le_bytes().to_vec()).expect("Failed to convert prefix to string") 63 } 64 } 65 66 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> From<T> 67 for AlphaObject<T, PREFIX> 68 { 69 #[inline] 70 fn from(data: T) -> Self { 71 Self(data) 72 } 73 } 74 75 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromBytes 76 for AlphaObject<T, PREFIX> 77 { 78 /// Reads data into a buffer. 79 #[inline] 80 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 81 Ok(Self(FromBytes::read_le(&mut reader)?)) 82 } 83 } 84 85 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> ToBytes 86 for AlphaObject<T, PREFIX> 87 { 88 /// Writes the data to a buffer. 89 #[inline] 90 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 91 self.0.write_le(&mut writer) 92 } 93 } 94 95 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromStr 96 for AlphaObject<T, PREFIX> 97 { 98 type Err = Error; 99 100 /// Reads in a bech32m string. 101 #[inline] 102 fn from_str(string: &str) -> Result<Self, Self::Err> { 103 let (hrp, data, variant) = bech32::decode(string)?; 104 if hrp.as_bytes() != PREFIX.to_le_bytes() { 105 bail!("Invalid prefix for a bech32m hash: {hrp}") 106 }; 107 if data.is_empty() { 108 bail!("Bech32m hash data is empty") 109 } 110 if variant != bech32::Variant::Bech32m { 111 bail!("Hash is not a bech32m hash") 112 } 113 Ok(Self::read_le(&*Vec::from_base32(&data)?)?) 114 } 115 } 116 117 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Display 118 for AlphaObject<T, PREFIX> 119 { 120 #[inline] 121 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 122 bech32::encode_to_fmt( 123 f, 124 &Self::prefix(), 125 self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(), 126 bech32::Variant::Bech32m, 127 ) 128 .expect("Failed to encode in bech32m") 129 } 130 } 131 132 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Debug 133 for AlphaObject<T, PREFIX> 134 { 135 #[inline] 136 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 137 write!(f, "AlphaObject {{ hrp: {:?}, data: {:?} }}", &Self::prefix(), self.0) 138 } 139 } 140 141 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Serialize 142 for AlphaObject<T, PREFIX> 143 { 144 #[inline] 145 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 146 match serializer.is_human_readable() { 147 true => serializer.collect_str(self), 148 false => ToBytesSerializer::serialize_with_size_encoding(self, serializer), 149 } 150 } 151 } 152 153 impl<'de, T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deserialize<'de> 154 for AlphaObject<T, PREFIX> 155 { 156 #[inline] 157 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 158 match deserializer.is_human_readable() { 159 true => FromStr::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom), 160 false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, &Self::prefix()), 161 } 162 } 163 } 164 165 impl<T: Default + Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Default 166 for AlphaObject<T, PREFIX> 167 { 168 fn default() -> Self { 169 Self(T::default()) 170 } 171 } 172 173 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deref 174 for AlphaObject<T, PREFIX> 175 { 176 type Target = T; 177 178 #[inline] 179 fn deref(&self) -> &Self::Target { 180 &self.0 181 } 182 } 183 184 impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Borrow<T> 185 for AlphaObject<T, PREFIX> 186 { 187 #[inline] 188 fn borrow(&self) -> &T { 189 &self.0 190 } 191 }