#![allow(dead_code)]
use std::ops::BitXor;
use base64::Engine;
use bs58::encode as bs58_encode;
use derive_more::{AsRef, Deref, Index, IndexMut, IntoIterator};
use hex::encode as hex_encode;
use num_bigint::BigInt;
use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use crate::config::DEFAULT_ADDRESS_VERSION;
#[derive(Debug, Serialize, Deserialize, AsRef, Deref, IntoIterator, Index, IndexMut)]
struct Bytes(Vec<u8>);
impl Bytes {
fn b_int(&self) -> Result<BigInt, &'static str> {
let bytes = self.0.as_slice().try_into().map_err(|_| "Failed to convert bytes to i128")?;
let i128_value = i128::from_be_bytes(bytes);
BigInt::from_i128(i128_value).ok_or("Failed to convert i128 to BigInt")
}
fn base64_encoded(&self) -> String {
base64::engine::general_purpose::STANDARD.encode(&self.0)
}
fn base58_encoded(&self) -> String {
bs58_encode(self.0.as_slice()).into_string()
}
fn base58_check_encoded(&self) -> String {
let checksum = &Sha256::digest(Sha256::digest(&self.0))[..4];
let mut bytes = self.0.clone();
bytes.extend_from_slice(checksum);
bs58_encode(&bytes).into_string()
}
fn no_prefix_hex(&self) -> String {
hex_encode(self.0.as_slice()).trim_start_matches("0x").to_string()
}
fn var_size(&self) -> usize {
std::mem::size_of::<usize>() + self.0.len()
}
fn scripthash_to_address(&self) -> String {
let mut script = vec![DEFAULT_ADDRESS_VERSION];
script.extend_from_slice(&self.0.iter().rev().copied().collect::<Vec<_>>());
let mut hasher = Sha256::new();
hasher.update(&script);
let checksum = &hasher.finalize()[..4];
let mut address = script;
address.extend_from_slice(checksum);
bs58_encode(&address).into_string()
}
fn to_padded(&self, length: usize, trailing: bool) -> Result<Bytes, &'static str> {
let bytes_len = self.0.len();
if bytes_len > length {
return Err("Input is too large");
}
let mut padded = vec![0u8; length];
let offset = if self.0.first() == Some(&0) { 1 } else { 0 };
if trailing {
padded[..bytes_len - offset].copy_from_slice(&self.0[offset..]);
} else {
padded[length - bytes_len + offset..].copy_from_slice(&self.0[offset..]);
}
Ok(Bytes(padded))
}
fn trim_trailing_bytes(&mut self, byte: u8) {
while self.0.last() == Some(&byte) {
self.0.pop();
}
}
}
impl BitXor for Bytes {
type Output = Result<Self, &'static str>;
fn bitxor(self, rhs: Self) -> Self::Output {
if self.0.len() != rhs.0.len() {
return Err("Arrays do not have the same length");
}
let bytes = self.0.iter().zip(rhs.0.iter()).map(|(x, y)| x ^ y).collect();
Ok(Bytes(bytes))
}
}
pub trait ReverseTrait {
fn reverse(&self) -> Self;
}
impl ReverseTrait for Vec<u8> {
fn reverse(&self) -> Self {
self.iter().rev().copied().collect()
}
}