use crate::abi::TypeAbi;
use crate::types::BoxedBytes;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Debug;
const ERR_BAD_H256_LENGTH: &[u8] = b"bad H256 length";
const ZERO_32: &[u8] = &[0u8; 32];
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub struct H256(Box<[u8; 32]>);
impl From<[u8; 32]> for H256 {
#[inline]
fn from(arr: [u8; 32]) -> Self {
H256(Box::new(arr))
}
}
impl<'a> From<&'a [u8; 32]> for H256 {
#[inline]
fn from(bytes: &'a [u8; 32]) -> Self {
H256(Box::new(*bytes))
}
}
impl<'a> From<&'a mut [u8; 32]> for H256 {
#[inline]
fn from(bytes: &'a mut [u8; 32]) -> Self {
H256(Box::new(*bytes))
}
}
impl From<Box<[u8; 32]>> for H256 {
#[inline]
fn from(bytes: Box<[u8; 32]>) -> Self {
H256(bytes)
}
}
impl H256 {
pub fn from_slice(slice: &[u8]) -> Self {
let mut i = 0;
let mut arr = [0u8; 32];
while i < 32 && i < slice.len() {
arr[i] = slice[i];
i += 1;
}
H256(Box::new(arr))
}
}
impl From<H256> for [u8; 32] {
#[inline]
fn from(s: H256) -> Self {
*(s.0)
}
}
impl AsRef<[u8]> for H256 {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsMut<[u8]> for H256 {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
impl H256 {
pub fn zero() -> Self {
use alloc::alloc::{alloc_zeroed, Layout};
unsafe {
let ptr = alloc_zeroed(Layout::new::<[u8; 32]>()) as *mut [u8; 32];
H256(Box::from_raw(ptr))
}
}
#[inline]
pub fn len_bytes() -> usize {
32
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.0.as_ref()
}
#[inline]
pub fn copy_to_array(&self, target: &mut [u8; 32]) {
target.copy_from_slice(&self.0[..]);
}
#[inline]
pub fn to_vec(&self) -> Vec<u8> {
self.0[..].to_vec()
}
#[inline]
pub fn as_ptr(&mut self) -> *const u8 {
self.0.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.0.as_mut_ptr()
}
pub fn is_zero(&self) -> bool {
self.as_bytes() == ZERO_32
}
pub fn into_boxed_bytes(self) -> BoxedBytes {
let raw = Box::into_raw(self.0) as *mut u8;
unsafe {
let bytes_box = Box::<[u8]>::from_raw(core::slice::from_raw_parts_mut(raw, 32));
bytes_box.into()
}
}
}
use dharitri_codec::*;
impl NestedEncode for H256 {
fn dep_encode<O: NestedEncodeOutput>(&self, dest: &mut O) -> Result<(), EncodeError> {
dest.write(&self.0[..]);
Ok(())
}
fn dep_encode_or_exit<O: NestedEncodeOutput, ExitCtx: Clone>(
&self,
dest: &mut O,
_: ExitCtx,
_: fn(ExitCtx, EncodeError) -> !,
) {
dest.write(&self.0[..]);
}
}
impl TopEncode for H256 {
fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
output.set_slice_u8(&self.0[..]);
Ok(())
}
fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
&self,
output: O,
_: ExitCtx,
_: fn(ExitCtx, EncodeError) -> !,
) {
output.set_slice_u8(&self.0[..]);
}
}
impl NestedDecode for H256 {
fn dep_decode<I: NestedDecodeInput>(input: &mut I) -> Result<Self, DecodeError> {
let mut res = H256::zero();
input.read_into(res.as_mut())?;
Ok(res)
}
fn dep_decode_or_exit<I: NestedDecodeInput, ExitCtx: Clone>(
input: &mut I,
c: ExitCtx,
exit: fn(ExitCtx, DecodeError) -> !,
) -> Self {
let mut res = H256::zero();
input.read_into_or_exit(res.as_mut(), c, exit);
res
}
}
impl H256 {
pub fn decode_from_boxed_bytes_or_exit<ExitCtx: Clone>(
input: Box<[u8]>,
c: ExitCtx,
exit: fn(ExitCtx, DecodeError) -> !,
) -> Self {
if input.len() != 32 {
exit(c, DecodeError::from(ERR_BAD_H256_LENGTH));
}
let raw = Box::into_raw(input);
let array_box = unsafe { Box::<[u8; 32]>::from_raw(raw as *mut [u8; 32]) };
H256(array_box)
}
}
impl TopDecode for H256 {
fn top_decode<I: TopDecodeInput>(input: I) -> Result<Self, DecodeError> {
match <[u8; 32]>::top_decode_boxed(input) {
Ok(array_box) => Ok(H256(array_box)),
Err(_) => Err(DecodeError::from(ERR_BAD_H256_LENGTH)),
}
}
fn top_decode_or_exit<I: TopDecodeInput, ExitCtx: Clone>(
input: I,
c: ExitCtx,
exit: fn(ExitCtx, DecodeError) -> !,
) -> Self {
H256::decode_from_boxed_bytes_or_exit(input.into_boxed_slice_u8(), c, exit)
}
}
impl TypeAbi for H256 {
fn type_name() -> String {
"H256".into()
}
}
#[cfg(test)]
mod h256_tests {
use super::*;
use alloc::vec::Vec;
use dharitri_codec::test_util::{check_top_encode, ser_deser_ok};
#[test]
fn test_h256_from_array() {
let addr = H256::from([4u8; 32]);
ser_deser_ok(addr, &[4u8; 32]);
}
#[test]
fn test_opt_h256() {
let addr = H256::from([4u8; 32]);
let mut expected: Vec<u8> = Vec::new();
expected.push(1u8);
expected.extend_from_slice(&[4u8; 32]);
ser_deser_ok(Some(addr), expected.as_slice());
}
#[test]
fn test_ser_h256_ref() {
let addr = H256::from([4u8; 32]);
let expected_bytes: &[u8] = &[4u8; 32 * 3];
let tuple = (&addr, &&&addr, addr.clone());
let serialized_bytes = check_top_encode(&tuple);
assert_eq!(serialized_bytes.as_slice(), expected_bytes);
}
#[test]
fn test_is_zero() {
assert!(H256::zero().is_zero());
}
#[test]
fn test_size_of() {
use core::mem::size_of;
assert_eq!(size_of::<H256>(), size_of::<usize>());
assert_eq!(size_of::<Option<H256>>(), size_of::<usize>());
}
#[test]
fn test_into_boxed_bytes() {
let array = b"32_bytes________________________";
let h256 = H256::from(array);
let bb = h256.into_boxed_bytes();
assert_eq!(bb.as_slice(), &array[..]);
}
}