Fix Dynamic hashing.
This commit is contained in:
parent
c02d702081
commit
859a18c6fd
@ -33,6 +33,8 @@ use fmt::Debug;
|
|||||||
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
||||||
use instant::Instant;
|
use instant::Instant;
|
||||||
|
|
||||||
|
const CHECKED: &str = "never fails because the type was checked";
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
use crate::fn_native::SendSync;
|
use crate::fn_native::SendSync;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@ -471,29 +473,27 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for Dynamic {
|
impl Hash for Dynamic {
|
||||||
|
/// Hash the [`Dynamic`] value.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the [`Dynamic`] value contains an unrecognized trait object.
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
std::mem::discriminant(&self.0).hash(state);
|
||||||
|
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
Union::Unit(_, _, _) => ().hash(state),
|
Union::Unit(_, _, _) => ().hash(state),
|
||||||
Union::Bool(value, _, _) => value.hash(state),
|
Union::Bool(b, _, _) => b.hash(state),
|
||||||
Union::Str(s, _, _) => s.hash(state),
|
Union::Str(s, _, _) => s.hash(state),
|
||||||
Union::Char(ch, _, _) => ch.hash(state),
|
Union::Char(c, _, _) => c.hash(state),
|
||||||
Union::Int(i, _, _) => i.hash(state),
|
Union::Int(i, _, _) => i.hash(state),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Union::Float(f, _, _) => f.hash(state),
|
Union::Float(f, _, _) => f.hash(state),
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(a, _, _) => a.as_ref().hash(state),
|
Union::Array(a, _, _) => a.as_ref().hash(state),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(m, _, _) => m.iter().for_each(|(key, value)| {
|
Union::Map(m, _, _) => m.as_ref().hash(state),
|
||||||
key.hash(state);
|
Union::FnPtr(f, _, _) => f.hash(state),
|
||||||
value.hash(state);
|
|
||||||
}),
|
|
||||||
Union::FnPtr(f, _, _) if f.is_curried() => {
|
|
||||||
unimplemented!(
|
|
||||||
"{} with curried arguments cannot be hashed",
|
|
||||||
self.type_name()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Union::FnPtr(f, _, _) => f.fn_name().hash(state),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(cell, _, _) => {
|
Union::Shared(cell, _, _) => {
|
||||||
@ -505,6 +505,55 @@ impl Hash for Dynamic {
|
|||||||
(*value).hash(state)
|
(*value).hash(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
Union::Variant(value, _, _) => {
|
||||||
|
let value = value.as_ref().as_ref();
|
||||||
|
let _type_id = value.type_id();
|
||||||
|
let _value_any = value.as_any();
|
||||||
|
|
||||||
|
if _type_id == TypeId::of::<u8>() {
|
||||||
|
TypeId::of::<u8>().hash(state);
|
||||||
|
_value_any.downcast_ref::<u8>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<u16>() {
|
||||||
|
TypeId::of::<u16>().hash(state);
|
||||||
|
_value_any.downcast_ref::<u16>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<u32>() {
|
||||||
|
TypeId::of::<u32>().hash(state);
|
||||||
|
_value_any.downcast_ref::<u32>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<u64>() {
|
||||||
|
TypeId::of::<u64>().hash(state);
|
||||||
|
_value_any.downcast_ref::<u64>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<i8>() {
|
||||||
|
TypeId::of::<i8>().hash(state);
|
||||||
|
_value_any.downcast_ref::<i8>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<i16>() {
|
||||||
|
TypeId::of::<i16>().hash(state);
|
||||||
|
_value_any.downcast_ref::<i16>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<i32>() {
|
||||||
|
TypeId::of::<i32>().hash(state);
|
||||||
|
_value_any.downcast_ref::<i32>().expect(CHECKED).hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<i64>() {
|
||||||
|
TypeId::of::<i64>().hash(state);
|
||||||
|
_value_any.downcast_ref::<i64>().expect(CHECKED).hash(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
|
if _type_id == TypeId::of::<u128>() {
|
||||||
|
TypeId::of::<u128>().hash(state);
|
||||||
|
_value_any
|
||||||
|
.downcast_ref::<u128>()
|
||||||
|
.expect(CHECKED)
|
||||||
|
.hash(state);
|
||||||
|
} else if _type_id == TypeId::of::<i128>() {
|
||||||
|
TypeId::of::<i128>().hash(state);
|
||||||
|
_value_any
|
||||||
|
.downcast_ref::<i128>()
|
||||||
|
.expect(CHECKED)
|
||||||
|
.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => unimplemented!("{} cannot be hashed", self.type_name()),
|
_ => unimplemented!("{} cannot be hashed", self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -573,8 +622,6 @@ impl fmt::Display for Dynamic {
|
|||||||
let _type_id = value.type_id();
|
let _type_id = value.type_id();
|
||||||
let _value_any = value.as_any();
|
let _value_any = value.as_any();
|
||||||
|
|
||||||
const CHECKED: &str = "never fails because the type was checked";
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
if _type_id == TypeId::of::<u8>() {
|
if _type_id == TypeId::of::<u8>() {
|
||||||
|
@ -263,7 +263,7 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
|||||||
|
|
||||||
/// A general function pointer, which may carry additional (i.e. curried) argument values
|
/// A general function pointer, which may carry additional (i.e. curried) argument values
|
||||||
/// to be passed onto a function during a call.
|
/// to be passed onto a function during a call.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct FnPtr(Identifier, StaticVec<Dynamic>);
|
pub struct FnPtr(Identifier, StaticVec<Dynamic>);
|
||||||
|
|
||||||
impl FnPtr {
|
impl FnPtr {
|
||||||
|
Loading…
Reference in New Issue
Block a user