thru_base/
bintrie_types.rs

1use std::fmt;
2
3use crate::bintrie_error::BinTrieError;
4use crate::tn_public_address::tn_public_address_encode;
5
6/// 32-byte hash value compatible with the C implementation
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
8pub struct Hash(pub [u8; 32]);
9
10/// 32-byte public key value compatible with the C implementation
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
12pub struct Pubkey(pub [u8; 32]);
13
14impl Hash {
15    pub fn new(bytes: [u8; 32]) -> Self {
16        Self(bytes)
17    }
18
19    pub fn as_bytes(&self) -> &[u8; 32] {
20        &self.0
21    }
22
23    pub fn from_slice(slice: &[u8]) -> Result<Self, BinTrieError> {
24        if slice.len() != 32 {
25            return Err(BinTrieError::InvalidHashLength);
26        }
27        let mut bytes = [0u8; 32];
28        bytes.copy_from_slice(slice);
29        Ok(Self(bytes))
30    }
31
32    pub fn is_zero(&self) -> bool {
33        self.0.iter().all(|&b| b == 0)
34    }
35}
36
37impl Pubkey {
38    pub fn new(bytes: [u8; 32]) -> Self {
39        Self(bytes)
40    }
41
42    pub fn as_bytes(&self) -> &[u8; 32] {
43        &self.0
44    }
45
46    pub fn from_slice(slice: &[u8]) -> Result<Self, BinTrieError> {
47        if slice.len() != 32 {
48            return Err(BinTrieError::InvalidPubkeyLength);
49        }
50        let mut bytes = [0u8; 32];
51        bytes.copy_from_slice(slice);
52        Ok(Self(bytes))
53    }
54
55    pub fn is_zero(&self) -> bool {
56        self.0.iter().all(|&b| b == 0)
57    }
58
59    /// Get the bit at the specified index (0-255)
60    /// This matches the C implementation: (pubkey->ul[idx/64] >> (idx%64)) & 1UL
61    pub fn get_bit(&self, bit_idx: u8) -> bool {
62        let qword_idx = (bit_idx / 64) as usize;
63        let bit_offset = bit_idx % 64;
64        if qword_idx >= 4 {
65            return false;
66        }
67        // Convert to u64 manually to match C implementation
68        let mut qwords = [0u64; 4];
69        for i in 0..4 {
70            let start = i * 8;
71            qwords[i] = u64::from_le_bytes([
72                self.0[start],
73                self.0[start + 1],
74                self.0[start + 2],
75                self.0[start + 3],
76                self.0[start + 4],
77                self.0[start + 5],
78                self.0[start + 6],
79                self.0[start + 7],
80            ]);
81        }
82        (qwords[qword_idx] >> bit_offset) & 1 == 1
83    }
84}
85
86impl fmt::Display for Hash {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "0x{}", hex::encode(&self.0))
89    }
90}
91
92impl fmt::Display for Pubkey {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(f, "0x{}", hex::encode(&self.0))
95    }
96}
97
98impl fmt::Debug for Hash {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        write!(f, "0x{}", hex::encode(&self.0))
101    }
102}
103
104impl fmt::Debug for Pubkey {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        let mut out = [0u8; 46];
107        tn_public_address_encode(&mut out, &self.0);
108        write!(
109            f,
110            "{}(0x{})",
111            String::from_utf8_lossy(&out).to_string(),
112            hex::encode(&self.0)
113        )
114    }
115}