use std::hash::{Hash, Hasher};
use indexmap::IndexMap;
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Bool(bool),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
F32(f32),
F64(f64),
Char(char),
Str(String),
Bytes(Vec<u8>),
None,
Some(Box<Value>),
Unit,
UnitStruct(&'static str),
UnitVariant {
name: &'static str,
variant_index: u32,
variant: &'static str,
},
NewtypeStruct(&'static str, Box<Value>),
NewtypeVariant {
name: &'static str,
variant_index: u32,
variant: &'static str,
value: Box<Value>,
},
Seq(Vec<Value>),
Tuple(Vec<Value>),
TupleStruct(&'static str, Vec<Value>),
TupleVariant {
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: Vec<Value>,
},
Map(IndexMap<Value, Value>),
Struct(&'static str, IndexMap<&'static str, Value>),
StructVariant {
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: IndexMap<&'static str, Value>,
},
}
impl Eq for Value {}
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
match self {
Value::Bool(v) => v.hash(state),
Value::I8(v) => v.hash(state),
Value::I16(v) => v.hash(state),
Value::I32(v) => v.hash(state),
Value::I64(v) => v.hash(state),
Value::I128(v) => v.hash(state),
Value::U8(v) => v.hash(state),
Value::U16(v) => v.hash(state),
Value::U32(v) => v.hash(state),
Value::U64(v) => v.hash(state),
Value::U128(v) => v.hash(state),
Value::F32(_) => panic!("f32 is not hashable"),
Value::F64(_) => panic!("f64 is not hashable"),
Value::Char(v) => v.hash(state),
Value::Str(v) => v.hash(state),
Value::Bytes(v) => v.hash(state),
Value::None => {}
Value::Some(v) => v.hash(state),
Value::Unit => {}
Value::UnitStruct(v) => v.hash(state),
Value::UnitVariant {
name,
variant_index,
variant,
} => {
name.hash(state);
variant_index.hash(state);
variant.hash(state);
}
Value::NewtypeStruct(name, value) => {
name.hash(state);
value.hash(state);
}
Value::NewtypeVariant {
name,
variant_index,
variant,
value,
} => {
name.hash(state);
variant_index.hash(state);
variant.hash(state);
value.hash(state);
}
Value::Seq(v) => v.hash(state),
Value::Tuple(v) => v.hash(state),
Value::TupleStruct(name, fields) => {
name.hash(state);
fields.hash(state);
}
Value::TupleVariant {
name,
variant_index,
variant,
fields,
} => {
name.hash(state);
variant_index.hash(state);
variant.hash(state);
fields.hash(state);
}
Value::Map(v) => {
for e in v {
e.hash(state)
}
}
Value::Struct(name, fields) => {
name.hash(state);
for e in fields {
e.hash(state)
}
}
Value::StructVariant {
name,
variant_index,
variant,
fields,
} => {
name.hash(state);
variant_index.hash(state);
variant.hash(state);
for e in fields {
e.hash(state)
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enum_size() {
println!("Size is {}", std::mem::size_of::<Value>());
}
}