/ console / network / src / helpers / object.rs
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  }