use crate::prelude::*; use derive_new::new; use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value}; use nu_source::{b, PrettyDebug, Spanned}; #[derive(Debug, new)] struct DebugEntry<'a> { key: &'a str, value: &'a Value, } impl<'a> PrettyDebug for DebugEntry<'a> { fn pretty(&self) -> DebugDocBuilder { (b::key(self.key.to_string()) + b::equals() + self.value.pretty().as_value()).group() } } pub trait DictionaryExt { fn get_data(&self, desc: &str) -> MaybeOwned<'_, Value>; fn keys(&self) -> indexmap::map::Keys; fn get_data_by_key(&self, name: Spanned<&str>) -> Option; fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value>; fn insert_data_at_key(&mut self, name: &str, value: Value); } impl DictionaryExt for Dictionary { fn get_data(&self, desc: &str) -> MaybeOwned<'_, Value> { match self.entries.get(desc) { Some(v) => MaybeOwned::Borrowed(v), None => MaybeOwned::Owned( UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(), ), } } fn keys(&self) -> indexmap::map::Keys { self.entries.keys() } fn get_data_by_key(&self, name: Spanned<&str>) -> Option { let result = self .entries .iter() .find(|(desc_name, _)| *desc_name == name.item)? .1; Some( result .value .clone() .into_value(Tag::new(result.anchor(), name.span)), ) } fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> { match self .entries .iter_mut() .find(|(desc_name, _)| *desc_name == name) { Some((_, v)) => Some(v), None => None, } } fn insert_data_at_key(&mut self, name: &str, value: Value) { self.entries.insert(name.to_string(), value); } } #[derive(Debug)] pub struct TaggedListBuilder { tag: Tag, pub list: Vec, } impl TaggedListBuilder { pub fn new(tag: impl Into) -> TaggedListBuilder { TaggedListBuilder { tag: tag.into(), list: vec![], } } pub fn push_value(&mut self, value: impl Into) { self.list.push(value.into()); } pub fn push_untagged(&mut self, value: impl Into) { self.list.push(value.into().into_value(self.tag.clone())); } pub fn into_value(self) -> Value { UntaggedValue::Table(self.list).into_value(self.tag) } pub fn into_untagged_value(self) -> UntaggedValue { UntaggedValue::Table(self.list).into_value(self.tag).value } } impl From for Value { fn from(input: TaggedListBuilder) -> Value { input.into_value() } }