#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
use core::fmt::{self, Display, Debug, Formatter, LowerHex, UpperHex};
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
use core::str::FromStr;
use core::ops::{Index, IndexMut, RangeFull};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::borrow::{Borrow, BorrowMut};
use core::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
use core::array::TryFromSliceError;
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
use crate::hex::{FromHex, ToHex, self};
use crate::{Wrapper, WrapperMut};
pub type Bytes16 = Array<u8, 16>;
pub type Bytes32 = Array<u8, 32>;
pub type Bytes64 = Array<u8, 64>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Array<T, const LEN: usize>([T; LEN]);
impl<T, const LEN: usize> Array<T, LEN> {
pub fn with(val: T) -> Self
where
T: Copy,
{
Self([val; LEN])
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.as_ref()
}
#[inline]
pub fn as_slice_mut(&mut self) -> &mut [T] {
self.as_mut()
}
#[allow(clippy::wrong_self_convention)]
#[cfg(any(test, feature = "std", feature = "alloc"))]
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.0.to_vec()
}
}
impl<const LEN: usize> Array<u8, LEN> {
#[cfg(feature = "rand")]
pub fn random() -> Self {
use rand::RngCore;
let mut entropy = [0u8; LEN];
rand::thread_rng().fill_bytes(&mut entropy);
Array::from_inner(entropy)
}
pub fn zero() -> Self {
Self([0u8; LEN])
}
}
impl<T, const LEN: usize> Array<T, LEN>
where
T: Default + Copy,
{
pub fn new() -> Self {
Default::default()
}
pub fn from_slice(slice: impl AsRef<[T]>) -> Option<Self> {
let slice = slice.as_ref();
if slice.len() != LEN {
return None;
}
let mut inner = [T::default(); LEN];
inner.copy_from_slice(slice);
Some(Self(inner))
}
}
impl<T, const LEN: usize> Default for Array<T, LEN>
where
T: Default + Copy,
{
fn default() -> Self {
let inner = [T::default(); LEN];
Self(inner)
}
}
impl<T, const LEN: usize> From<[T; LEN]> for Array<T, LEN> {
fn from(array: [T; LEN]) -> Self {
Array(array)
}
}
impl<T, const LEN: usize> TryFrom<&[T]> for Array<T, LEN>
where
T: Copy + Default,
{
type Error = TryFromSliceError;
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
<[T; LEN]>::try_from(value).map(Self)
}
}
impl<T, const LEN: usize> AsRef<[T]> for Array<T, LEN> {
#[inline]
fn as_ref(&self) -> &[T] {
self.0.as_ref()
}
}
impl<T, const LEN: usize> AsMut<[T]> for Array<T, LEN> {
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self.0.as_mut()
}
}
impl<T, const LEN: usize> Borrow<[T]> for Array<T, LEN> {
#[inline]
fn borrow(&self) -> &[T] {
self.0.borrow()
}
}
impl<T, const LEN: usize> BorrowMut<[T]> for Array<T, LEN> {
#[inline]
fn borrow_mut(&mut self) -> &mut [T] {
self.0.borrow_mut()
}
}
impl<T, const LEN: usize> Index<usize> for Array<T, LEN> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<Range<usize>> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: Range<usize>) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<RangeTo<usize>> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: RangeTo<usize>) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<RangeFrom<usize>> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<RangeInclusive<usize>> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<RangeToInclusive<usize>> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> Index<RangeFull> for Array<T, LEN> {
type Output = [T];
#[inline]
fn index(&self, index: RangeFull) -> &Self::Output {
&self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<usize> for Array<T, LEN> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<Range<usize>> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<RangeTo<usize>> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<RangeFrom<usize>> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<RangeInclusive<usize>> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<RangeToInclusive<usize>> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> IndexMut<RangeFull> for Array<T, LEN> {
#[inline]
fn index_mut(&mut self, index: RangeFull) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T, const LEN: usize> From<T> for Array<T, LEN>
where
T: Into<[T; LEN]>,
{
fn from(array: T) -> Self {
Self(array.into())
}
}
impl<T, const LEN: usize> Wrapper for Array<T, LEN> {
type Inner = [T; LEN];
#[inline]
fn from_inner(inner: Self::Inner) -> Self {
Self(inner)
}
#[inline]
fn as_inner(&self) -> &Self::Inner {
&self.0
}
#[inline]
fn into_inner(self) -> Self::Inner {
self.0
}
}
impl<T, const LEN: usize> WrapperMut for Array<T, LEN> {
fn as_inner_mut(&mut self) -> &mut Self::Inner {
&mut self.0
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> Display for Array<u8, LEN> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
LowerHex::fmt(self, f)
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> Debug for Array<u8, LEN> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Array<{}>({})", LEN, self.to_hex())
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> FromStr for Array<u8, LEN> {
type Err = hex::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_hex(s)
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> FromHex for Array<u8, LEN> {
fn from_byte_iter<I>(iter: I) -> Result<Self, hex::Error>
where
I: Iterator<Item = Result<u8, hex::Error>> + ExactSizeIterator + DoubleEndedIterator,
{
let vec = Vec::<u8>::from_byte_iter(iter)?;
if vec.len() != 32 {
return Err(hex::Error::InvalidLength(32, vec.len()));
}
let mut id = [0u8; LEN];
id.copy_from_slice(&vec);
Ok(Array(id))
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> LowerHex for Array<u8, LEN> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(
f,
"{}..{}",
self.0[..4].to_hex(),
self.0[(self.0.len() - 4)..].to_hex()
)
} else {
f.write_str(&self.0.to_hex())
}
}
}
#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
impl<const LEN: usize> UpperHex for Array<u8, LEN> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(
f,
"{}..{}",
self.0[..4].to_hex().to_ascii_uppercase(),
self.0[(self.0.len() - 4)..].to_hex().to_ascii_uppercase()
)
} else {
f.write_str(&self.0.to_hex().to_ascii_uppercase())
}
}
}
#[cfg(all(feature = "serde", feature = "hex"))]
pub(crate) mod serde_helpers {
use serde::{Deserialize, Deserializer, Serializer, Serialize};
use crate::Array;
use crate::hex::{FromHex, ToHex};
impl<const LEN: usize> Serialize for Array<u8, LEN> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.as_ref().to_hex())
}
}
impl<'de, const LEN: usize> Deserialize<'de> for Array<u8, LEN> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
String::deserialize(deserializer)
.and_then(|string| {
let vec = Vec::<u8>::from_hex(&string)
.map_err(|_| D::Error::custom("wrong hex data"))?;
if vec.len() != LEN {
return Err(D::Error::custom("Wrong 32-byte slice data length"));
}
let mut slice32 = [0u8; LEN];
slice32.copy_from_slice(&vec[..LEN]);
Ok(slice32)
})
.map(Self)
}
}
}
#[cfg(test)]
mod test {
use core::str::FromStr;
use super::*;
use crate::Wrapper;
use crate::hex::FromHex;
#[test]
fn test_slice32_str() {
let s = "a3401bcceb26201b55978ff705fecf7d8a0a03598ebeccf2a947030b91a0ff53";
let slice32 = Bytes32::from_hex(s).unwrap();
assert_eq!(Bytes32::from_str(s), Ok(slice32));
assert_eq!(Bytes32::from_hex(&s.to_uppercase()), Ok(slice32));
assert_eq!(
Bytes32::from_str(&s[..30]),
Err(hex::Error::InvalidLength(32, 15))
);
assert_eq!(&slice32.to_string(), s);
assert_eq!(format!("{:x}", slice32), s);
assert_eq!(format!("{:X}", slice32), s.to_uppercase());
assert_eq!(format!("{:?}", slice32), format!("Array<32>({})", s));
}
#[test]
fn test_encoding() {
let s = "a3401bcceb26201b55978ff705fecf7d8a0a03598ebeccf2a947030b91a0ff53";
let slice32 = Array::from_hex(s).unwrap();
let data = [
0xa3, 0x40, 0x1b, 0xcc, 0xeb, 0x26, 0x20, 0x1b, 0x55, 0x97, 0x8f, 0xf7, 0x05, 0xfe,
0xcf, 0x7d, 0x8a, 0x0a, 0x03, 0x59, 0x8e, 0xbe, 0xcc, 0xf2, 0xa9, 0x47, 0x03, 0x0b,
0x91, 0xa0, 0xff, 0x53,
];
assert_eq!(Bytes32::from_slice(&data), Some(slice32));
assert_eq!(Bytes32::from_slice(&data[..30]), None);
assert_eq!(&slice32.to_vec(), &data);
assert_eq!(&slice32.as_inner()[..], &data);
assert_eq!(slice32.to_inner(), data);
assert_eq!(slice32.into_inner(), data);
}
}