use crate::stable_hash::{self, FieldAddress};
use crate::types::*;
#[repr(u8)]
pub enum ValueVariant {
String = 1, Int = 2, BigDecimal = 3, Bool = 4, List = 5, Bytes = 6, BigInt = 7, Int8 = 8, }
impl From<ValueVariant> for u8 {
#[inline(always)]
fn from(value: ValueVariant) -> Self {
value as u8
}
}
pub struct ValueTypeHasher<T: Hashable> {
pub field: &'static str,
pub data: T,
}
impl<T> stable_hash::StableHash for ValueTypeHasher<T>
where
T: Hashable,
{
fn stable_hash<H: stable_hash::StableHasher>(&self, field_address: H::Addr, state: &mut H) {
self.field.stable_hash(field_address.child(0), state);
<T as Hashable>::with_new(&self.data, field_address.child(1), state);
}
}
pub trait Hashable: stable_hash::StableHash {
fn with_new<H: stable_hash::StableHasher>(&self, field_address: H::Addr, state: &mut H) {
<Self as stable_hash::StableHash>::stable_hash(self, field_address.child(0), state);
state.write(field_address, &[Self::variant_numeric()]);
}
fn variant() -> ValueVariant;
#[inline(always)]
fn variant_numeric() -> u8 {
Self::variant() as u8
}
}
impl<'a, T: Hashable> Hashable for &'a T {
#[inline(always)]
fn variant() -> ValueVariant {
<T as Hashable>::variant()
}
}
impl<T: Hashable> Hashable for Vec<T> {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::List
}
}
impl<T: Hashable> Hashable for Option<T> {
#[inline(always)]
fn variant() -> ValueVariant {
<T as Hashable>::variant()
}
fn with_new<H: stable_hash::StableHasher>(&self, field_address: H::Addr, state: &mut H) {
if let Some(val) = self {
<T as Hashable>::with_new(val, field_address, state)
}
}
}
mod string_like {
use super::*;
impl Hashable for String {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::String
}
}
impl<'a> Hashable for &'a str {
#[inline(always)]
fn variant() -> ValueVariant {
<String as Hashable>::variant()
}
}
}
impl Hashable for i16 {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Int
}
}
impl Hashable for i32 {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Int
}
}
impl Hashable for BigDecimal {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::BigDecimal
}
}
impl Hashable for bool {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Bool
}
}
impl Hashable for Vec<u8> {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Bytes
}
}
impl Hashable for crate::types::Bytes {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::String
}
}
impl Hashable for BigInt {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::BigInt
}
}
impl Hashable for i64 {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Int8
}
}
impl<const N: usize> Hashable for H<N> {
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Bytes
}
}
impl<const N: usize> Hashable for U<N>
where
U<N>: crate::types::ByteArray,
<U<N> as crate::types::ByteArray>::Array: AsRef<[u8]>,
{
#[inline(always)]
fn variant() -> ValueVariant {
ValueVariant::Bytes
}
}