use std::hash::Hash;
use std::hash::Hasher;
use super::Shape;
use super::ShapeCase;
impl Hash for Shape {
fn hash<H: Hasher>(&self, state: &mut H) {
self.case_hash.hash(state);
}
}
impl Hash for ShapeCase {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::Bool(value) => ("::Bool", value).hash(state),
Self::String(value) => ("::String", value).hash(state),
Self::Int(value) => ("::Int", value).hash(state),
Self::Float => "::Float".hash(state),
Self::Null => "::Null".hash(state),
Self::Array { prefix, tail } => ("::Array", prefix, tail).hash(state),
Self::Object { fields, rest } => {
let fields_hash = fields.iter().fold(0, |acc, (key, value)| {
let mut fields_hasher = std::collections::hash_map::DefaultHasher::new();
key.hash(&mut fields_hasher);
value.hash(&mut fields_hasher);
acc ^ fields_hasher.finish() as u64
});
("::Object", fields_hash, rest).hash(state)
}
Self::One(shapes) => {
let xor_hash = shapes.iter().fold(0, |acc, shape| {
let mut shape_hasher = std::collections::hash_map::DefaultHasher::new();
shape.hash(&mut shape_hasher);
acc ^ shape_hasher.finish() as u64
});
("::One", xor_hash).hash(state)
}
Self::All(shapes) => {
let xor_hash = shapes.iter().fold(0, |acc, shape| {
let mut shape_hasher = std::collections::hash_map::DefaultHasher::new();
shape.hash(&mut shape_hasher);
acc ^ shape_hasher.finish() as u64
});
("::All", xor_hash).hash(state)
}
Self::Name(name, subpath) => ("::Name", name, subpath).hash(state),
Self::None => "::None".hash(state),
Self::Error {
message,
range,
partial,
} => ("::Error", message, range, partial).hash(state),
}
}
}
impl ShapeCase {
pub fn compute_hash(&self) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.hash(&mut hasher);
hasher.finish() as u64
}
}