use std::collections::HashMap; #[derive(PartialEq, Debug)] pub enum Value { None, True, False, Number(f64), String(String), Table { arr: Vec, map: HashMap, } } impl From for Value { fn from(v: i32) -> Value { Value::Number(f64::from(v)) } } impl From for Value { fn from(v: f32) -> Value { Value::Number(f64::from(v)) } } impl From for Value { fn from(v: f64) -> Value { Value::Number(v) } } impl From for Value { fn from(v: String) -> Value { Value::String(v) } } impl From<&str> for Value { fn from(v: &str) -> Value { Value::String(v.to_string()) } } impl From for Value { fn from(v: bool) -> Value { match v { true => Value::True, false => Value::False, } } } impl> From> for Value { fn from(v: Vec) -> Value { let mut vec: Vec = Vec::new(); for val in v { vec.push(val.into()); } Value::Table { arr: vec, map: HashMap::new() } } } impl> From> for Value { fn from(v: HashMap) -> Value { let mut map: HashMap = HashMap::new(); for (k, v) in v { map.insert(k, v.into()); } Value::Table { arr: Vec::new(), map} } } impl> From> for Value { fn from(v: Option) -> Value { match v { Some(v) => v.into(), None => Value::None, } } } pub trait FromValue { fn from_value(v: Value) -> Result where Self: Sized; } impl FromValue for f64 { fn from_value(v: Value) -> Result { match v { Value::Number(v) => Ok(v), _ => Err("Value is not a number"), } } } impl FromValue for bool { fn from_value(v: Value) -> Result { match v { Value::True => Ok(true), Value::False => Ok(false), _ => Err("Value is not a boolean"), } } } impl FromValue for String { fn from_value(v: Value) -> Result { match v { Value::String(v) => Ok(v), _ => Err("Value is not a string"), } } } impl Value { pub fn extract(self) -> Result { FromValue::from_value(self) } }