use std::collections::HashMap; use std::fmt; use crate::error::CrimResult; use crate::{Identifier,IdentifierValue}; pub type Context = HashMap; pub trait MappedStructure<'a> { fn get_value(&'a self, id: &str) -> Option>; } impl<'a> MappedStructure<'a> for Context { fn get_value(&'a self, id: &str) -> Option> { self.get(id).map(|v|Into::>::into(v)) } } pub trait MappedList<'a> { fn get_index(&'a self, id: usize) -> Option>; fn for_each(&'a self, func: &dyn Fn(&MappedValue<'a>, &mut String) -> CrimResult<()>) -> CrimResult; } impl<'a, T: MappedStructure<'a>> MappedList<'a> for Vec { fn get_index(&'a self, id: usize) -> Option> { if let Some(x) = self.get(id) { Some(MappedValue::<'a>::Struct(x)) } else { None } } fn for_each(&'a self, func: &dyn Fn(&MappedValue<'a>, &mut String) -> CrimResult<()>) -> CrimResult { let mut buf = String::new(); for i in self { func( &MappedValue::Struct(i), &mut buf )?; } Ok(buf) } } impl<'a> MappedList<'a> for Vec { fn get_index(&'a self, id: usize) -> Option> { if let Some(x) = self.get(id) { Some(x.into()) } else { None } } fn for_each(&'a self, func: &dyn Fn(&MappedValue<'a>, &mut String) -> CrimResult<()>) -> CrimResult { let mut buf = String::new(); for i in self { func( &Into::>::into( i ), &mut buf )?; } Ok(buf) } } impl<'a> MappedList<'a> for Vec> { fn get_index(&'a self, id: usize) -> Option> { if let Some(x) = self.get(id) { Some(*x) } else { None } } fn for_each(&'a self, func: &dyn Fn(&MappedValue<'a>, &mut String) -> CrimResult<()>) -> CrimResult { let mut buf = String::new(); for i in self { func( i, &mut buf )?; } Ok(buf) } } pub type MappedHash<'a> = HashMap>; impl<'a> MappedStructure<'a> for MappedHash<'a> { fn get_value(&'a self, id: &str) -> Option> { self.get(id).copied() } } #[derive(Copy,Clone)] pub enum MappedValue<'a> { Struct(&'a dyn MappedStructure<'a>), List(&'a dyn MappedList<'a>), Str(&'a str), String(&'a String), Int8(i8), Int16(i16), Int32(i32), Int64(i64), UInt8(u8), UInt16(u16), UInt32(u32), UInt64(u64), Float32(f32), Float64(f64), Bool(bool), } impl<'a> fmt::Debug for MappedValue<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MappedValue::<'a>::Struct(_) => write!(f, "MappedValue"), MappedValue::<'a>::List(_) => write!(f, "MappedList"), MappedValue::<'a>::Str(v) => write!(f, "{:?}", v), MappedValue::<'a>::String(v) => write!(f, "{:?}", v), MappedValue::<'a>::Int8(v) => write!(f, "{:?}", v), MappedValue::<'a>::Int16(v) => write!(f, "{:?}", v), MappedValue::<'a>::Int32(v) => write!(f, "{:?}", v), MappedValue::<'a>::Int64(v) => write!(f, "{:?}", v), MappedValue::<'a>::UInt8(v) => write!(f, "{:?}", v), MappedValue::<'a>::UInt16(v) => write!(f, "{:?}", v), MappedValue::<'a>::UInt32(v) => write!(f, "{:?}", v), MappedValue::<'a>::UInt64(v) => write!(f, "{:?}", v), MappedValue::<'a>::Float32(v) => write!(f, "{:?}", v), MappedValue::<'a>::Float64(v) => write!(f, "{:?}", v), MappedValue::<'a>::Bool(v) => write!(f, "{:?}", v), } } } macro_rules! basic_mapped_value_from { ( $x:ident, $y:ident ) => { impl<'a> From<&$x> for MappedValue<'a> { fn from(val: &$x) -> MappedValue<'a> { MappedValue::$y(*val) } } }; } basic_mapped_value_from!(i8, Int8); basic_mapped_value_from!(i16, Int16); basic_mapped_value_from!(i32, Int32); basic_mapped_value_from!(i64, Int64); basic_mapped_value_from!(u8, UInt8); basic_mapped_value_from!(u16, UInt16); basic_mapped_value_from!(u32, UInt32); basic_mapped_value_from!(u64, UInt64); basic_mapped_value_from!(f32, Float32); basic_mapped_value_from!(f64, Float64); basic_mapped_value_from!(bool, Bool); impl<'a> MappedStructure<'a> for HashMap { fn get_value(&'a self, id: &str) -> Option> { self.get(id).map(|x|MappedValue::String(x)) } } impl<'a> From<&'a String> for MappedValue<'a> { fn from(val: &'a String ) -> MappedValue<'a> { MappedValue::String(val) } } impl<'a, T: MappedStructure<'a>> From<&'a Vec> for MappedValue<'a> { fn from(val: &'a Vec ) -> MappedValue<'a> { MappedValue::List(val) } } impl<'a,T: MappedStructure<'a>> From<&'a T> for MappedValue<'a> { fn from(val: &'a T ) -> MappedValue<'a> { MappedValue::Struct(val) } } pub struct StatefulContext<'a> { root: &'a dyn MappedStructure<'a>, local: &'a dyn MappedStructure<'a>, } impl<'a> StatefulContext<'a> { pub fn root( root: &'a dyn MappedStructure<'a> ) -> Self { Self { root, local: root, } } pub fn local(&self, local: &'a dyn MappedStructure<'a> ) -> Self { Self { root: self.root, local } } pub fn full( root: &'a dyn MappedStructure<'a>, local: &'a dyn MappedStructure<'a> ) -> Self { Self { root, local } } pub fn get_value(&self, id: &[IdentifierValue]) -> Option> { let mut value : Option = if id[0] == IdentifierValue::Root { Some(MappedValue::Struct(self.root)) } else { Some(MappedValue::Struct(self.local)) }; for idpart in id { match idpart { IdentifierValue::Root => { continue; } IdentifierValue::Name(name) => { if let Some(MappedValue::Struct(s)) = value && let Some(nv) = s.get_value( &name ) { value.replace( nv ); } else { return None; } } IdentifierValue::Index(_) => { return None; } } } value } } impl<'a> From<&'a Value> for MappedValue<'a> { fn from(value: &'a Value) -> Self { match value { Value::Dictionary(ctx) => MappedValue::Struct(ctx), Value::List(list) => MappedValue::List(list), Value::String(s) => MappedValue::String(s), Value::Int(i) => MappedValue::Int64(*i), Value::Float(f) => MappedValue::Float64(*f), Value::Bool(b) => MappedValue::Bool(*b), Value::Identifier(_identifier) => panic!("Identifier!?"), } } } #[derive(Debug,Clone)] pub enum Value { Dictionary(Context), List(Vec), String(String), Int(i64), Float(f64), Bool(bool), Identifier(Identifier), } impl From<&str> for Value { fn from(val: &str ) -> Value { Value::String(val.into()) } } impl From for Value { fn from(val: String) -> Value { Value::String(val) } } impl From for Value { fn from(val: i64) -> Value { Value::Int(val) } } impl From for Value { fn from(val: f64) -> Value { Value::Float(val) } } impl From for Value { fn from(val: bool) -> Value { Value::Bool(val) } } impl From> for Value { fn from(val: Vec) -> Value { Value::List(val) } } impl From<&[Value]> for Value { fn from(val: &[Value]) -> Value { Value::List(Vec::from(val)) } } impl From for Value { fn from(val: Context) -> Value { Value::Dictionary(val) } } impl From<[(String,Value); N]> for Value { fn from(val: [(String,Value); N]) -> Value { Value::Dictionary(HashMap::from(val)) } } /* impl MappedStructure for Value { fn get_value(&self, id: &Identifier) -> Option { if id.len() == 0 { return Some(self); } match Value { Value::Dictionary(dict) => { } } let mut cur_val : Option<&Value> = Some(&self); for idx in 0..id.len() { if let IdentifierValue::Name(s) = &id[idx] && let Some(Value::Dictionary(d)) = &cur_val { cur_val.replace( if let Some(v) = d.get(s) { v } else { return None; }); } } return cur_val.cloned(); } } */