use crate::prelude::*; use crate::object::{Primitive, Value}; use derive_new::new; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::cmp::{Ordering, PartialOrd}; use std::fmt; #[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, new)] pub struct Dictionary { pub entries: IndexMap>, } impl PartialOrd for Dictionary { fn partial_cmp(&self, other: &Dictionary) -> Option { let this: Vec<&String> = self.entries.keys().collect(); let that: Vec<&String> = other.entries.keys().collect(); if this != that { return this.partial_cmp(&that); } let this: Vec<&Value> = self.entries.values().collect(); let that: Vec<&Value> = self.entries.values().collect(); this.partial_cmp(&that) } } impl From>> for Dictionary { fn from(input: IndexMap>) -> Dictionary { let mut out = IndexMap::default(); for (key, value) in input { out.insert(key, value); } Dictionary::new(out) } } impl Ord for Dictionary { fn cmp(&self, other: &Dictionary) -> Ordering { let this: Vec<&String> = self.entries.keys().collect(); let that: Vec<&String> = other.entries.keys().collect(); if this != that { return this.cmp(&that); } let this: Vec<&Value> = self.entries.values().collect(); let that: Vec<&Value> = self.entries.values().collect(); this.cmp(&that) } } impl PartialOrd for Dictionary { fn partial_cmp(&self, _other: &Value) -> Option { Some(Ordering::Less) } } impl PartialEq for Dictionary { fn eq(&self, other: &Value) -> bool { match other { Value::Object(d) => self == d, _ => false, } } } impl Dictionary { crate fn add(&mut self, name: impl Into, value: Value) { self.entries.insert(name.into(), value); } crate fn copy_dict(&self) -> Dictionary { let mut out = Dictionary::default(); for (key, value) in self.entries.iter() { out.add(key.clone(), value.copy()); } out } pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> { match self.entries.get(desc) { Some(v) => MaybeOwned::Borrowed(v), None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)), } } crate fn get_data_by_key(&self, name: &str) -> Option<&Spanned> { match self .entries .iter() .find(|(desc_name, _)| *desc_name == name) { Some((_, v)) => Some(v), None => None, } } crate fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Dictionary"); for (desc, value) in self.entries.iter() { debug.field(desc, &value.debug()); } debug.finish() } } #[derive(Debug)] pub struct SpannedDictBuilder { span: Span, dict: IndexMap>, } impl SpannedDictBuilder { pub fn new(span: impl Into) -> SpannedDictBuilder { SpannedDictBuilder { span: span.into(), dict: IndexMap::default(), } } pub fn insert(&mut self, key: impl Into, value: impl Into) { self.dict .insert(key.into(), value.into().spanned(self.span)); } pub fn insert_spanned( &mut self, key: impl Into, value: impl Into>, ) { self.dict.insert(key.into(), value.into()); } pub fn into_spanned_value(self) -> Spanned { Value::Object(Dictionary { entries: self.dict }).spanned(self.span) } } impl From for Spanned { fn from(input: SpannedDictBuilder) -> Spanned { input.into_spanned_value() } }