alloy_trie/hash_builder/
value.rsuse alloc::vec::Vec;
use alloy_primitives::{hex, B256};
use core::fmt;
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HashBuilderValue {
#[cfg_attr(feature = "serde", serde(with = "hex"))]
buf: Vec<u8>,
kind: HashBuilderValueKind,
}
impl Default for HashBuilderValue {
fn default() -> Self {
Self { buf: Vec::with_capacity(128), kind: HashBuilderValueKind::default() }
}
}
impl fmt::Debug for HashBuilderValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_ref().fmt(f)
}
}
#[cfg(feature = "arbitrary")]
impl<'u> arbitrary::Arbitrary<'u> for HashBuilderValue {
fn arbitrary(g: &mut arbitrary::Unstructured<'u>) -> arbitrary::Result<Self> {
let kind = HashBuilderValueKind::arbitrary(g)?;
let buf = match kind {
HashBuilderValueKind::Bytes => Vec::arbitrary(g)?,
HashBuilderValueKind::Hash => B256::arbitrary(g)?.to_vec(),
};
Ok(Self { buf, kind })
}
}
#[cfg(feature = "arbitrary")]
impl proptest::arbitrary::Arbitrary for HashBuilderValue {
type Parameters = ();
type Strategy = proptest::strategy::BoxedStrategy<Self>;
fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
use proptest::prelude::*;
proptest::arbitrary::any::<HashBuilderValueKind>()
.prop_flat_map(|kind| {
let range = match kind {
HashBuilderValueKind::Bytes => 0..=128,
HashBuilderValueKind::Hash => 32..=32,
};
proptest::collection::vec(any::<u8>(), range)
.prop_map(move |buf| Self { buf, kind })
})
.boxed()
}
}
impl HashBuilderValue {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn as_ref(&self) -> HashBuilderValueRef<'_> {
match self.kind {
HashBuilderValueKind::Bytes => HashBuilderValueRef::Bytes(&self.buf),
HashBuilderValueKind::Hash => {
debug_assert_eq!(self.buf.len(), 32);
HashBuilderValueRef::Hash(unsafe { self.buf[..].try_into().unwrap_unchecked() })
}
}
}
pub fn as_slice(&self) -> &[u8] {
&self.buf
}
pub fn set_bytes_owned(&mut self, bytes: Vec<u8>) {
self.buf = bytes;
self.kind = HashBuilderValueKind::Bytes;
}
#[inline]
pub fn set_from_ref(&mut self, value: HashBuilderValueRef<'_>) {
self.buf.clear();
self.buf.extend_from_slice(value.as_slice());
self.kind = value.kind();
}
#[inline]
pub fn clear(&mut self) {
self.buf.clear();
self.kind = HashBuilderValueKind::default();
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(derive_arbitrary::Arbitrary, proptest_derive::Arbitrary))]
enum HashBuilderValueKind {
#[default]
Bytes,
Hash,
}
pub enum HashBuilderValueRef<'a> {
Bytes(&'a [u8]),
Hash(&'a B256),
}
impl<'a> HashBuilderValueRef<'a> {
pub const fn as_slice(&self) -> &'a [u8] {
match *self {
HashBuilderValueRef::Bytes(bytes) => bytes,
HashBuilderValueRef::Hash(hash) => hash.as_slice(),
}
}
const fn kind(&self) -> HashBuilderValueKind {
match *self {
HashBuilderValueRef::Bytes(_) => HashBuilderValueKind::Bytes,
HashBuilderValueRef::Hash(_) => HashBuilderValueKind::Hash,
}
}
}
impl fmt::Debug for HashBuilderValueRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match *self {
HashBuilderValueRef::Bytes(_) => "Bytes",
HashBuilderValueRef::Hash(_) => "Hash",
};
let slice = hex::encode_prefixed(self.as_slice());
write!(f, "{name}({slice})")
}
}