use crate::{
decode::{Decode, DecodeError, Decoder},
encode::{Encode, Encoder, Size},
fmt::Hex,
log::{FromTopic, ToTopic, TopicHash},
primitive::{Primitive, Word},
};
use ethprim::Keccak;
use std::{
borrow::{Borrow, Cow},
fmt::{self, Debug, Formatter},
mem,
ops::{Deref, DerefMut},
};
#[derive(Clone, Copy, Default, Eq, PartialEq)]
#[repr(transparent)]
pub struct Bytes<T>(pub T)
where
T: ?Sized;
impl Bytes<[u8]> {
#[allow(clippy::needless_lifetimes)]
pub fn new<'a>(bytes: &'a [u8]) -> &'a Bytes<[u8]> {
unsafe { mem::transmute(bytes) }
}
#[allow(clippy::needless_lifetimes)]
pub fn borrowed<'a>(bytes: &'a [u8]) -> Cow<'a, Bytes<[u8]>> {
Cow::Borrowed(Self::new(bytes))
}
}
impl Bytes<Vec<u8>> {
pub fn as_borrowed(&self) -> &Bytes<[u8]> {
Bytes::new(&self[..])
}
}
impl<T> AsRef<[u8]> for Bytes<T>
where
T: AsRef<[u8]> + ?Sized,
{
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<T> AsMut<[u8]> for Bytes<T>
where
T: AsMut<[u8]> + ?Sized,
{
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
impl<T> Debug for Bytes<T>
where
T: AsRef<[u8]> + ?Sized,
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("Bytes").field(&Hex(self.0.as_ref())).finish()
}
}
impl<T> Deref for Bytes<T>
where
T: ?Sized,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Bytes<T>
where
T: ?Sized,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Borrow<Bytes<[u8]>> for Bytes<Vec<u8>> {
fn borrow(&self) -> &Bytes<[u8]> {
self.as_borrowed()
}
}
impl ToOwned for Bytes<[u8]> {
type Owned = Bytes<Vec<u8>>;
fn to_owned(&self) -> Self::Owned {
Bytes(self.0.to_owned())
}
}
macro_rules! impl_primitive_for_fixed_bytes {
($($n:literal,)*) => {$(
impl Primitive for Bytes<[u8; $n]> {
fn to_word(&self) -> Word {
let mut word = Word::default();
word[..$n].copy_from_slice(self.as_ref());
word
}
fn from_word(word: Word) -> Self {
let mut bytes = Self::default();
bytes.copy_from_slice(&word[..$n]);
bytes
}
}
)*};
}
impl_primitive_for_fixed_bytes! {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
}
impl Encode for Bytes<[u8]> {
fn size(&self) -> Size {
Bytes(&self.0).size()
}
fn encode(&self, encoder: &mut Encoder) {
Bytes(&self.0).encode(encoder)
}
}
impl ToTopic for Bytes<[u8]> {
fn to_topic(&self) -> Word {
Bytes(&self.0).to_topic()
}
}
impl TopicHash for Bytes<[u8]> {
fn update_hash(&self, hasher: &mut Keccak) {
Bytes(&self.0).update_hash(hasher);
}
}
impl Encode for Bytes<&'_ [u8]> {
fn size(&self) -> Size {
let words = (self.len() + 31) / 32;
Size::Dynamic(1 + words, 0)
}
fn encode(&self, encoder: &mut Encoder) {
encoder.write(&self.len());
encoder.write_bytes(self);
}
}
impl ToTopic for Bytes<&'_ [u8]> {
fn to_topic(&self) -> Word {
let mut hasher = Keccak::new();
hasher.update(self);
*hasher.finalize()
}
}
impl TopicHash for Bytes<&'_ [u8]> {
fn update_hash(&self, hasher: &mut Keccak) {
hasher.update(self);
static ZEROS: Word = [0; 32];
let padding = (32 - (self.len() % 32)) % 32;
hasher.update(&ZEROS[..padding]);
}
}
impl Encode for Bytes<Vec<u8>> {
fn size(&self) -> Size {
Bytes(&self[..]).size()
}
fn encode(&self, encoder: &mut Encoder) {
Bytes(&self[..]).encode(encoder)
}
}
impl Decode for Bytes<Vec<u8>> {
fn is_dynamic() -> bool {
true
}
fn decode(decoder: &mut Decoder) -> Result<Self, DecodeError> {
let len = decoder.read_size()?;
Ok(Self(decoder.read_bytes(len)?.to_owned()))
}
}
impl ToTopic for Bytes<Vec<u8>> {
fn to_topic(&self) -> Word {
Bytes(&self[..]).to_topic()
}
}
impl FromTopic for Bytes<Vec<u8>> {
fn from_topic(_: Word) -> Self {
Self::default()
}
}
impl TopicHash for Bytes<Vec<u8>> {
fn update_hash(&self, hasher: &mut Keccak) {
Bytes(&self[..]).update_hash(hasher);
}
}