Skip to content

Commit

Permalink
feat(primitives): add some impls
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Jun 30, 2023
1 parent 9e01fd2 commit b7d1bee
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 21 deletions.
67 changes: 51 additions & 16 deletions crates/primitives/src/bits/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,72 @@ pub struct FixedBytes<const N: usize>(#[into_iterator(owned, ref, ref_mut)] pub
crate::impl_fixed_bytes_traits!(FixedBytes<N>, N, const);

impl<const N: usize> Default for FixedBytes<N> {
#[inline]
fn default() -> Self {
Self::ZERO
}
}

impl<'a, const N: usize> From<&'a [u8; N]> for FixedBytes<N> {
/// Constructs a hash type from the given reference
/// to the bytes array of fixed length.
///
/// # Note
///
/// The given bytes are interpreted in big endian order.
impl<const N: usize> From<&[u8; N]> for FixedBytes<N> {
#[inline]
fn from(bytes: &'a [u8; N]) -> Self {
fn from(bytes: &[u8; N]) -> Self {
Self(*bytes)
}
}

impl<'a, const N: usize> From<&'a mut [u8; N]> for FixedBytes<N> {
/// Constructs a hash type from the given reference
/// to the mutable bytes array of fixed length.
///
/// # Note
///
/// The given bytes are interpreted in big endian order.
impl<const N: usize> From<&mut [u8; N]> for FixedBytes<N> {
#[inline]
fn from(bytes: &'a mut [u8; N]) -> Self {
fn from(bytes: &mut [u8; N]) -> Self {
Self(*bytes)
}
}

/// Tries to create a `FixedBytes<N>` by copying from a slice `&[u8]`. Succeeds
/// if `slice.len() == N`.
impl<const N: usize> TryFrom<&[u8]> for FixedBytes<N> {
type Error = core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
<&Self>::try_from(slice).map(|this| *this)
}
}

/// Tries to create a `FixedBytes<N>` by copying from a mutable slice `&mut
/// [u8]`. Succeeds if `slice.len() == N`.
impl<const N: usize> TryFrom<&mut [u8]> for FixedBytes<N> {
type Error = core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &mut [u8]) -> Result<Self, Self::Error> {
Self::try_from(&*slice)
}
}

/// Tries to create a ref `FixedBytes<N>` by copying from a slice `&[u8]`.
/// Succeeds if `slice.len() == N`.
impl<'a, const N: usize> TryFrom<&'a [u8]> for &'a FixedBytes<N> {
type Error = core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &'a [u8]) -> Result<&'a FixedBytes<N>, Self::Error> {
// SAFETY: `FixedBytes<N>` is `repr(transparent)` for `[u8; N]`
<&[u8; N]>::try_from(slice).map(|array_ref| unsafe { core::mem::transmute(array_ref) })
}
}

/// Tries to create a ref `FixedBytes<N>` by copying from a mutable slice `&mut
/// [u8]`. Succeeds if `slice.len() == N`.
impl<'a, const N: usize> TryFrom<&'a mut [u8]> for &'a mut FixedBytes<N> {
type Error = core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &'a mut [u8]) -> Result<&'a mut FixedBytes<N>, Self::Error> {
// SAFETY: `FixedBytes<N>` is `repr(transparent)` for `[u8; N]`
<&mut [u8; N]>::try_from(slice).map(|array_ref| unsafe { core::mem::transmute(array_ref) })
}
}

// Ideally this would be:
// `impl<const N: usize> From<FixedBytes<N>> for Uint<N * 8>`
// `impl<const N: usize> From<Uint<N / 8>> for FixedBytes<N>`
Expand Down
44 changes: 44 additions & 0 deletions crates/primitives/src/bits/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,50 @@ macro_rules! wrap_fixed_bytes {
}
}

impl ::core::convert::TryFrom<&[u8]> for $name {
type Error = ::core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
<&Self>::try_from(slice).map(|this| *this)
}
}

impl ::core::convert::TryFrom<&mut [u8]> for $name {
type Error = ::core::array::TryFromSliceError;

#[inline]
fn try_from(slice: &mut [u8]) -> Result<Self, Self::Error> {
Self::try_from(&*slice)
}
}

impl<'a> ::core::convert::TryFrom<&'a [u8]> for &'a $name {
type Error = ::core::array::TryFromSliceError;

#[inline]
#[allow(unsafe_code)]
fn try_from(slice: &'a [u8]) -> Result<&'a $name, Self::Error> {
// SAFETY: `$name` is `repr(transparent)` for `FixedBytes<$n>`
// and consequently `[u8; $n]`
<&[u8; $n] as ::core::convert::TryFrom<&[u8]>>::try_from(slice)
.map(|array_ref| unsafe { core::mem::transmute(array_ref) })
}
}

impl<'a> ::core::convert::TryFrom<&'a mut [u8]> for &'a mut $name {
type Error = ::core::array::TryFromSliceError;

#[inline]
#[allow(unsafe_code)]
fn try_from(slice: &'a mut [u8]) -> Result<&'a mut $name, Self::Error> {
// SAFETY: `$name` is `repr(transparent)` for `FixedBytes<$n>`
// and consequently `[u8; $n]`
<&mut [u8; $n] as ::core::convert::TryFrom<&mut [u8]>>::try_from(slice)
.map(|array_ref| unsafe { core::mem::transmute(array_ref) })
}
}

impl ::core::convert::AsRef<[u8; $n]> for $name {
#[inline]
fn as_ref(&self) -> &[u8; $n] {
Expand Down
45 changes: 40 additions & 5 deletions crates/primitives/src/bytes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use alloc::{string::String, vec::Vec};
use core::{borrow::Borrow, fmt, ops::Deref};
use core::{
borrow::Borrow,
fmt,
ops::{Deref, DerefMut},
};

#[cfg(feature = "rlp")]
mod rlp;
Expand Down Expand Up @@ -33,33 +37,44 @@ impl fmt::LowerHex for Bytes {
}

impl Deref for Bytes {
type Target = [u8];
type Target = bytes::Bytes;

#[inline]
fn deref(&self) -> &[u8] {
self.as_ref()
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for Bytes {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl AsRef<[u8]> for Bytes {
#[inline]
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Borrow<[u8]> for Bytes {
#[inline]
fn borrow(&self) -> &[u8] {
self.as_ref()
}
}

impl FromIterator<u8> for Bytes {
#[inline]
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
Self(iter.into_iter().collect::<bytes::Bytes>())
Self(bytes::Bytes::from_iter(iter))
}
}

impl<'a> FromIterator<&'a u8> for Bytes {
#[inline]
fn from_iter<T: IntoIterator<Item = &'a u8>>(iter: T) -> Self {
Self(iter.into_iter().copied().collect::<bytes::Bytes>())
}
Expand All @@ -69,6 +84,7 @@ impl IntoIterator for Bytes {
type Item = u8;
type IntoIter = bytes::buf::IntoIter<bytes::Bytes>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
Expand All @@ -78,72 +94,84 @@ impl<'a> IntoIterator for &'a Bytes {
type Item = &'a u8;
type IntoIter = core::slice::Iter<'a, u8>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_ref().iter()
}
}

impl From<bytes::Bytes> for Bytes {
#[inline]
fn from(src: bytes::Bytes) -> Self {
Self(src)
}
}

impl From<Vec<u8>> for Bytes {
#[inline]
fn from(src: Vec<u8>) -> Self {
Self(src.into())
}
}

impl<const N: usize> From<[u8; N]> for Bytes {
#[inline]
fn from(src: [u8; N]) -> Self {
src.to_vec().into()
}
}

impl<'a, const N: usize> From<&'a [u8; N]> for Bytes {
#[inline]
fn from(src: &'a [u8; N]) -> Self {
src.to_vec().into()
}
}

impl From<&'static [u8]> for Bytes {
#[inline]
fn from(value: &'static [u8]) -> Self {
Self(value.into())
}
}

impl From<&'static str> for Bytes {
#[inline]
fn from(value: &'static str) -> Self {
Self(value.into())
}
}

impl PartialEq<[u8]> for Bytes {
#[inline]
fn eq(&self, other: &[u8]) -> bool {
self[..] == *other
}
}

impl PartialEq<Bytes> for [u8] {
#[inline]
fn eq(&self, other: &Bytes) -> bool {
*self == other[..]
}
}

impl PartialEq<Vec<u8>> for Bytes {
#[inline]
fn eq(&self, other: &Vec<u8>) -> bool {
self[..] == other[..]
}
}

impl PartialEq<Bytes> for Vec<u8> {
#[inline]
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}

impl PartialEq<bytes::Bytes> for Bytes {
#[inline]
fn eq(&self, other: &bytes::Bytes) -> bool {
other == self.as_ref()
}
Expand Down Expand Up @@ -194,6 +222,13 @@ impl Bytes {
Self(bytes::Bytes::from_static(bytes))
}

/// Creates a new `Bytes` instance from a slice by copying it.
#[inline]
pub fn copy_from_slice(src: &[u8]) -> Self {
Self(bytes::Bytes::copy_from_slice(src))
}

#[inline]
fn hex_encode(&self) -> String {
hex::encode_prefixed(self.0.as_ref())
}
Expand Down
6 changes: 6 additions & 0 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ pub use signed::{BigIntConversionError, ParseSignedError, Sign, Signed};
mod utils;
pub use utils::keccak256;

#[doc(no_inline)]
pub use ::hex;
#[doc(no_inline)]
pub use hex_literal::{self, hex};
#[doc(no_inline)]
pub use ruint::{self, uint, Uint};
#[doc(no_inline)]
pub use tiny_keccak::{self, Hasher, Keccak};

#[cfg(feature = "serde")]
#[doc(no_inline)]
pub use ::hex::serde as serde_hex;

// Not public API.
#[doc(hidden)]
pub mod private {
Expand Down

0 comments on commit b7d1bee

Please sign in to comment.