ethers_primitives 0.2.2

Primitive types for ethereum, including Rlp/ABI encode/decode support
Documentation
//! Contract abi `bytes<M>` and bytes type support. those types can aslo be used with eip715 or tx signature.

use std::fmt::Display;

use crate::hex::{FromEtherHex, ToEtherHex};

use hex::FromHexError;
// use concat_idents::concat_idents;
use serde::{de, Deserialize, Serialize};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum BytesErrors {
    #[error("Inputs data is out of bytes<M> range ")]
    BytesMOutOfRange,

    #[error("{0}")]
    FromHexError(#[from] FromHexError),
}

/// Type mapping for `bytes<M>` of contract abi
#[derive(Debug, PartialEq, Clone, Eq, Hash, Default)]
pub struct BytesM<const LEN: usize>(pub [u8; 32]);

impl<const LEN: usize> Display for BytesM<LEN> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0.to_eth_hex())
    }
}

impl<const LEN: usize> AsRef<[u8]> for BytesM<LEN> {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl<const LEN: usize> TryFrom<&str> for BytesM<LEN> {
    type Error = BytesErrors;
    fn try_from(value: &str) -> Result<Self, Self::Error> {
        let buff = Vec::<u8>::from_eth_hex(value)?;

        if buff.len() > 32 {
            return Err(BytesErrors::BytesMOutOfRange);
        }

        let mut temp = [0u8; 32];

        temp[..LEN].copy_from_slice(&buff[..LEN]);

        Ok(Self(temp))
    }
}

impl<const LEN: usize> Serialize for BytesM<LEN> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        if serializer.is_human_readable() {
            serializer.serialize_str(&self.0.to_eth_hex())
        } else {
            // AbiSerialize/EIp715Serializer use struct name to handle dispatch.
            let buff = &self.0;

            let name = format!("bytes{}", LEN);

            let static_name = unsafe { &*(&name as *const String) };

            serializer.serialize_newtype_struct(static_name.as_str(), buff)
        }
    }
}

impl<'de, const LEN: usize> Deserialize<'de> for BytesM<LEN> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            let data = String::deserialize(deserializer)?;

            let buff = Vec::<u8>::from_eth_hex(data).map_err(serde::de::Error::custom)?;

            if buff.len() > 32 {
                return Err(BytesErrors::BytesMOutOfRange).map_err(serde::de::Error::custom);
            }

            let mut temp = [0u8; 32];

            temp[..buff.len()].copy_from_slice(&buff[..buff.len()]);

            Ok(Self(temp))
        } else {
            let name = format!("bytes{}", LEN);

            let static_name = unsafe { &*(&name as *const String) };

            let buff = deserializer
                .deserialize_newtype_struct(static_name.as_str(), BytesVisitor::default())?;

            if buff.len() > 32 {
                return Err(BytesErrors::BytesMOutOfRange).map_err(serde::de::Error::custom);
            }

            let mut temp = [0u8; 32];

            temp[..LEN].copy_from_slice(&buff[..LEN]);

            Ok(Self(temp))
        }
    }
}

impl<const LEN: usize> From<[u8; LEN]> for BytesM<LEN> {
    fn from(value: [u8; LEN]) -> Self {
        Self::from(&value)
    }
}

impl<const LEN: usize> From<&[u8; LEN]> for BytesM<LEN> {
    fn from(value: &[u8; LEN]) -> Self {
        let mut buff = [0u8; 32];

        buff[..LEN].copy_from_slice(value);

        Self(buff)
    }
}

#[derive(Debug, Default)]
pub(crate) struct BytesVisitor;

impl<'de> de::Visitor<'de> for BytesVisitor {
    type Value = Vec<u8>;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "expect bytes/bytes<M>")
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(v)
    }
}

/// Type mapping for `bytes` of contract abi
#[derive(Debug, PartialEq, Clone, Eq, Default)]
pub struct Bytes(pub Vec<u8>);

impl Display for Bytes {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0.to_eth_hex())
    }
}

impl TryFrom<&str> for Bytes {
    type Error = BytesErrors;
    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Ok(Self(Vec::<u8>::from_eth_hex(value)?))
    }
}

impl Serialize for Bytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        if serializer.is_human_readable() {
            serializer.serialize_str(&self.0.to_eth_hex())
        } else {
            serializer.serialize_newtype_struct("bytes", &self.0)
        }
    }
}

impl<'de> Deserialize<'de> for Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            let data = String::deserialize(deserializer)?;

            let buff = Vec::<u8>::from_eth_hex(data).map_err(serde::de::Error::custom)?;

            Ok(Self(buff))
        } else {
            let buff = deserializer.deserialize_newtype_struct("bytes", BytesVisitor::default())?;

            Ok(Self(buff))
        }
    }
}

impl From<&[u8]> for Bytes {
    fn from(value: &[u8]) -> Self {
        Self(value.to_vec())
    }
}

impl From<Vec<u8>> for Bytes {
    fn from(value: Vec<u8>) -> Self {
        Self(value)
    }
}

impl<const LEN: usize> From<&[u8; LEN]> for Bytes {
    fn from(value: &[u8; LEN]) -> Self {
        Self(value.to_vec())
    }
}

impl<const LEN: usize> From<[u8; LEN]> for Bytes {
    fn from(value: [u8; LEN]) -> Self {
        Self(value.to_vec())
    }
}

pub type Bytes1 = BytesM<1>;
pub type Bytes32 = BytesM<32>;

#[cfg(test)]
mod tests {
    use std::fmt::Debug;

    use serde::Deserialize;
    use serde_ethabi::{from_abi, to_abi};

    use crate::hex::{FromEtherHex, ToEtherHex};

    use super::*;

    fn check<'de, V: Deserialize<'de> + Debug + PartialEq>(v: V, data: &str) {
        let data = Vec::<u8>::from_eth_hex(data).unwrap();

        let expected: V = from_abi(data).unwrap();

        assert_eq!(v, expected);
    }
    #[test]
    fn test_bytes() {
        assert_eq!(
            to_abi(#[allow(unused)]&([BytesM::from(b"abc"),BytesM::from(b"def")])).unwrap().to_eth_hex(),
            "0x61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000"
        );

        check(#[allow(unused)]([BytesM::from(b"abc"),BytesM::from(b"def")]), "0x61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000");

        assert_eq!(
            to_abi(&(Bytes::from(b"dave"),true,[1usize,2,3].as_slice())).unwrap().to_eth_hex(),
            "0x0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"
        );

        check((Bytes::from(b"dave"),true,[1usize,2,3].to_vec()), "0x0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003");

        assert_eq!(
            to_abi(&(0x123usize,[0x456usize,0x789].as_slice(),BytesM::from(b"1234567890"),Bytes::from(b"Hello, world!"))).unwrap().to_eth_hex(),
            "0x00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000"
        );

        check((0x123usize,[0x456usize,0x789].to_vec(),BytesM::from(b"1234567890"),Bytes::from(b"Hello, world!")),
            "0x00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000");

        assert_eq!(
            to_abi(&(
                [[1usize, 2].as_slice(), [3usize].as_slice()].as_slice(),
                ["one", "two", "three"].as_slice()
            ))
            .unwrap()
            .to_eth_hex(),
            "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000"
        );

        check((
                [[1usize, 2].to_vec(), [3usize].to_vec()].to_vec(),
                ["one".to_owned(), "two".to_owned(), "three".to_owned()].to_vec()
            ),"0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000");
    }
}