1use std::ops::BitXor;
2
3use bs58::encode as bs58_encode;
4use derive_more::{AsRef, Deref, Index, IndexMut, IntoIterator};
5use hex::encode as hex_encode;
6use num_bigint::BigInt;
7use num_traits::FromPrimitive;
8use serde::{Deserialize, Serialize};
9use sha2::{Digest, Sha256};
10
11#[derive(Debug, Serialize, Deserialize, AsRef, Deref, IntoIterator, Index, IndexMut)]
14struct Bytes(Vec<u8>);
15
16impl Bytes {
17 fn b_int(&self) -> Result<BigInt, &'static str> {
18 let bytes = self.0.as_slice().try_into().map_err(|_| "Failed to convert bytes to i128")?;
19
20 let i128_value = i128::from_be_bytes(bytes);
21 BigInt::from_i128(i128_value).ok_or("Failed to convert i128 to BigInt")
22 }
23
24 fn base64_encoded(&self) -> String {
25 base64::encode(&self.0)
26 }
27
28 fn base58_encoded(&self) -> String {
29 bs58_encode(self.0.as_slice()).into_string()
30 }
31
32 fn base58_check_encoded(&self) -> String {
33 let checksum = &Sha256::digest(&Sha256::digest(&self.0))[..4];
34 let mut bytes = self.0.clone();
35 bytes.extend_from_slice(checksum);
36 bs58_encode(&bytes).into_string()
37 }
38
39 fn no_prefix_hex(&self) -> String {
40 hex_encode(self.0.as_slice()).trim_start_matches("0x").to_string()
41 }
42
43 fn var_size(&self) -> usize {
44 std::mem::size_of::<usize>() + self.0.len()
45 }
46
47 fn scripthash_to_address(&self) -> String {
48 let mut script = vec![0x17];
49 script.extend_from_slice(&self.0.iter().rev().copied().collect::<Vec<_>>());
50
51 let mut hasher = Sha256::new();
52 hasher.update(&script);
53 let checksum = &hasher.finalize()[..4];
54
55 let mut address = script;
56 address.extend_from_slice(checksum);
57
58 bs58_encode(&address).into_string()
59 }
60
61 fn to_padded(&self, length: usize, trailing: bool) -> Result<Bytes, &'static str> {
62 let bytes_len = self.0.len();
63 if bytes_len > length {
64 return Err("Input is too large");
65 }
66
67 let mut padded = vec![0u8; length];
68 let offset = if self.0.first() == Some(&0) { 1 } else { 0 };
69
70 if trailing {
71 padded[..bytes_len - offset].copy_from_slice(&self.0[offset..]);
72 } else {
73 padded[length - bytes_len + offset..].copy_from_slice(&self.0[offset..]);
74 }
75
76 Ok(Bytes(padded))
77 }
78
79 fn trim_trailing_bytes(&mut self, byte: u8) {
80 while self.0.last() == Some(&byte) {
81 self.0.pop();
82 }
83 }
84}
85
86impl BitXor for Bytes {
87 type Output = Result<Self, &'static str>;
88
89 fn bitxor(self, rhs: Self) -> Self::Output {
90 if self.0.len() != rhs.0.len() {
91 return Err("Arrays do not have the same length");
92 }
93
94 let bytes = self.0.iter().zip(rhs.0.iter()).map(|(x, y)| x ^ y).collect();
95
96 Ok(Bytes(bytes))
97 }
98}
99
100pub trait ReverseTrait {
101 fn reverse(&self) -> Self;
102}
103
104impl ReverseTrait for Vec<u8> {
105 fn reverse(&self) -> Self {
106 self.iter().rev().copied().collect()
107 }
108}