use std::fmt;
use crate::bintrie_error::BinTrieError;
use crate::tn_public_address::tn_public_address_encode;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Hash(pub [u8; 32]);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Pubkey(pub [u8; 32]);
impl Hash {
pub fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
pub fn from_slice(slice: &[u8]) -> Result<Self, BinTrieError> {
if slice.len() != 32 {
return Err(BinTrieError::InvalidHashLength);
}
let mut bytes = [0u8; 32];
bytes.copy_from_slice(slice);
Ok(Self(bytes))
}
pub fn is_zero(&self) -> bool {
self.0.iter().all(|&b| b == 0)
}
}
impl Pubkey {
pub fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
pub fn from_slice(slice: &[u8]) -> Result<Self, BinTrieError> {
if slice.len() != 32 {
return Err(BinTrieError::InvalidPubkeyLength);
}
let mut bytes = [0u8; 32];
bytes.copy_from_slice(slice);
Ok(Self(bytes))
}
pub fn is_zero(&self) -> bool {
self.0.iter().all(|&b| b == 0)
}
pub fn get_bit(&self, bit_idx: u8) -> bool {
let qword_idx = (bit_idx / 64) as usize;
let bit_offset = bit_idx % 64;
if qword_idx >= 4 {
return false;
}
let mut qwords = [0u64; 4];
for i in 0..4 {
let start = i * 8;
qwords[i] = u64::from_le_bytes([
self.0[start],
self.0[start + 1],
self.0[start + 2],
self.0[start + 3],
self.0[start + 4],
self.0[start + 5],
self.0[start + 6],
self.0[start + 7],
]);
}
(qwords[qword_idx] >> bit_offset) & 1 == 1
}
}
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{}", hex::encode(&self.0))
}
}
impl fmt::Display for Pubkey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{}", hex::encode(&self.0))
}
}
impl fmt::Debug for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{}", hex::encode(&self.0))
}
}
impl fmt::Debug for Pubkey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut out = [0u8; 46];
tn_public_address_encode(&mut out, &self.0);
write!(
f,
"{}(0x{})",
String::from_utf8_lossy(&out).to_string(),
hex::encode(&self.0)
)
}
}