2019-11-21 15:33:14 +01:00
|
|
|
use crate::data::base::{Primitive, UntaggedValue, Value};
|
2019-05-16 00:58:44 +02:00
|
|
|
use crate::prelude::*;
|
2019-06-01 07:50:16 +02:00
|
|
|
use derive_new::new;
|
2019-11-04 16:47:03 +01:00
|
|
|
use getset::Getters;
|
2019-05-15 20:14:51 +02:00
|
|
|
use indexmap::IndexMap;
|
2019-11-21 15:33:14 +01:00
|
|
|
use nu_source::Spanned;
|
|
|
|
use nu_source::{b, PrettyDebug};
|
2019-11-04 16:47:03 +01:00
|
|
|
use pretty::{BoxAllocator, DocAllocator};
|
2019-07-03 19:37:09 +02:00
|
|
|
use serde::{Deserialize, Serialize};
|
2019-05-17 17:55:50 +02:00
|
|
|
use std::cmp::{Ordering, PartialOrd};
|
2019-05-10 18:59:12 +02:00
|
|
|
|
2019-11-04 16:47:03 +01:00
|
|
|
#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, Getters, new)]
|
2019-05-10 18:59:12 +02:00
|
|
|
pub struct Dictionary {
|
2019-11-04 16:47:03 +01:00
|
|
|
#[get = "pub"]
|
2019-11-21 15:33:14 +01:00
|
|
|
pub entries: IndexMap<String, Value>,
|
2019-05-10 18:59:12 +02:00
|
|
|
}
|
|
|
|
|
2019-11-04 16:47:03 +01:00
|
|
|
#[derive(Debug, new)]
|
|
|
|
struct DebugEntry<'a> {
|
|
|
|
key: &'a str,
|
2019-11-21 15:33:14 +01:00
|
|
|
value: &'a Value,
|
2019-11-04 16:47:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> PrettyDebug for DebugEntry<'a> {
|
2019-11-21 15:33:14 +01:00
|
|
|
fn pretty(&self) -> DebugDocBuilder {
|
|
|
|
(b::key(self.key.to_string()) + b::equals() + self.value.pretty().as_value()).group()
|
2019-11-04 16:47:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PrettyDebug for Dictionary {
|
2019-11-21 15:33:14 +01:00
|
|
|
fn pretty(&self) -> DebugDocBuilder {
|
2019-11-04 16:47:03 +01:00
|
|
|
BoxAllocator
|
|
|
|
.text("(")
|
|
|
|
.append(
|
|
|
|
BoxAllocator
|
|
|
|
.intersperse(
|
|
|
|
self.entries()
|
|
|
|
.iter()
|
|
|
|
.map(|(key, value)| DebugEntry::new(key, value).to_doc()),
|
|
|
|
BoxAllocator.space(),
|
|
|
|
)
|
|
|
|
.nest(1)
|
|
|
|
.group(),
|
|
|
|
)
|
|
|
|
.append(BoxAllocator.text(")"))
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 17:55:50 +02:00
|
|
|
impl PartialOrd for Dictionary {
|
2019-06-24 02:55:31 +02:00
|
|
|
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
|
2019-07-03 19:37:09 +02:00
|
|
|
let this: Vec<&String> = self.entries.keys().collect();
|
|
|
|
let that: Vec<&String> = other.entries.keys().collect();
|
2019-06-24 02:55:31 +02:00
|
|
|
|
|
|
|
if this != that {
|
|
|
|
return this.partial_cmp(&that);
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
let this: Vec<&Value> = self.entries.values().collect();
|
|
|
|
let that: Vec<&Value> = self.entries.values().collect();
|
2019-06-24 02:55:31 +02:00
|
|
|
|
|
|
|
this.partial_cmp(&that)
|
2019-05-17 17:55:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
impl From<IndexMap<String, Value>> for Dictionary {
|
|
|
|
fn from(input: IndexMap<String, Value>) -> Dictionary {
|
2019-06-01 07:50:16 +02:00
|
|
|
let mut out = IndexMap::default();
|
|
|
|
|
|
|
|
for (key, value) in input {
|
2019-07-03 19:37:09 +02:00
|
|
|
out.insert(key, value);
|
2019-06-01 07:50:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Dictionary::new(out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 17:55:50 +02:00
|
|
|
impl Ord for Dictionary {
|
2019-06-24 02:55:31 +02:00
|
|
|
fn cmp(&self, other: &Dictionary) -> Ordering {
|
2019-07-03 19:37:09 +02:00
|
|
|
let this: Vec<&String> = self.entries.keys().collect();
|
|
|
|
let that: Vec<&String> = other.entries.keys().collect();
|
2019-06-24 02:55:31 +02:00
|
|
|
|
|
|
|
if this != that {
|
|
|
|
return this.cmp(&that);
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
let this: Vec<&Value> = self.entries.values().collect();
|
|
|
|
let that: Vec<&Value> = self.entries.values().collect();
|
2019-06-24 02:55:31 +02:00
|
|
|
|
|
|
|
this.cmp(&that)
|
2019-05-17 17:55:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd<Value> for Dictionary {
|
|
|
|
fn partial_cmp(&self, _other: &Value) -> Option<Ordering> {
|
|
|
|
Some(Ordering::Less)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<Value> for Dictionary {
|
|
|
|
fn eq(&self, other: &Value) -> bool {
|
2019-11-21 15:33:14 +01:00
|
|
|
match &other.value {
|
|
|
|
UntaggedValue::Row(d) => self == d,
|
2019-05-17 17:55:50 +02:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 18:59:12 +02:00
|
|
|
impl Dictionary {
|
2019-08-29 14:16:11 +02:00
|
|
|
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
2019-05-24 20:48:33 +02:00
|
|
|
match self.entries.get(desc) {
|
2019-05-15 20:14:51 +02:00
|
|
|
Some(v) => MaybeOwned::Borrowed(v),
|
2019-11-21 15:33:14 +01:00
|
|
|
None => MaybeOwned::Owned(
|
|
|
|
UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
|
|
|
|
),
|
2019-05-10 18:59:12 +02:00
|
|
|
}
|
|
|
|
}
|
2019-05-17 17:55:50 +02:00
|
|
|
|
2019-11-04 16:47:03 +01:00
|
|
|
pub fn keys(&self) -> impl Iterator<Item = &String> {
|
|
|
|
self.entries.keys()
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
|
2019-11-04 16:47:03 +01:00
|
|
|
let result = self
|
2019-05-24 20:48:33 +02:00
|
|
|
.entries
|
|
|
|
.iter()
|
2019-11-04 16:47:03 +01:00
|
|
|
.find(|(desc_name, _)| *desc_name == name.item)?
|
|
|
|
.1;
|
|
|
|
|
|
|
|
Some(
|
|
|
|
result
|
2019-11-21 15:33:14 +01:00
|
|
|
.value
|
2019-11-04 16:47:03 +01:00
|
|
|
.clone()
|
2019-11-21 15:33:14 +01:00
|
|
|
.into_value(Tag::new(result.anchor(), name.span)),
|
2019-11-04 16:47:03 +01:00
|
|
|
)
|
2019-05-17 17:55:50 +02:00
|
|
|
}
|
2019-06-22 05:43:37 +02:00
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub(crate) fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> {
|
2019-10-20 13:55:56 +02:00
|
|
|
match self
|
|
|
|
.entries
|
|
|
|
.iter_mut()
|
|
|
|
.find(|(desc_name, _)| *desc_name == name)
|
|
|
|
{
|
|
|
|
Some((_, v)) => Some(v),
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub(crate) fn insert_data_at_key(&mut self, name: &str, value: Value) {
|
2019-11-04 16:47:03 +01:00
|
|
|
self.entries.insert(name.to_string(), value);
|
2019-06-22 05:43:37 +02:00
|
|
|
}
|
2019-05-10 18:59:12 +02:00
|
|
|
}
|
2019-07-08 18:44:53 +02:00
|
|
|
|
2019-09-02 07:37:13 +02:00
|
|
|
#[derive(Debug)]
|
2019-08-01 03:58:42 +02:00
|
|
|
pub struct TaggedListBuilder {
|
2019-09-03 09:43:37 +02:00
|
|
|
tag: Tag,
|
2019-11-21 15:33:14 +01:00
|
|
|
pub list: Vec<Value>,
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
|
2019-08-01 03:58:42 +02:00
|
|
|
impl TaggedListBuilder {
|
2019-08-05 10:54:29 +02:00
|
|
|
pub fn new(tag: impl Into<Tag>) -> TaggedListBuilder {
|
2019-08-01 03:58:42 +02:00
|
|
|
TaggedListBuilder {
|
2019-08-05 10:54:29 +02:00
|
|
|
tag: tag.into(),
|
2019-07-09 06:31:26 +02:00
|
|
|
list: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn push_value(&mut self, value: impl Into<Value>) {
|
|
|
|
self.list.push(value.into());
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn push_untagged(&mut self, value: impl Into<UntaggedValue>) {
|
|
|
|
self.list.push(value.into().into_value(self.tag.clone()));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_value(self) -> Value {
|
|
|
|
UntaggedValue::Table(self.list).into_value(self.tag)
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn into_untagged_value(self) -> UntaggedValue {
|
|
|
|
UntaggedValue::Table(self.list).into_value(self.tag).value
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
impl From<TaggedListBuilder> for Value {
|
|
|
|
fn from(input: TaggedListBuilder) -> Value {
|
|
|
|
input.into_value()
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-08 18:44:53 +02:00
|
|
|
#[derive(Debug)]
|
2019-08-01 03:58:42 +02:00
|
|
|
pub struct TaggedDictBuilder {
|
2019-08-05 10:54:29 +02:00
|
|
|
tag: Tag,
|
2019-11-21 15:33:14 +01:00
|
|
|
dict: IndexMap<String, Value>,
|
2019-07-08 18:44:53 +02:00
|
|
|
}
|
|
|
|
|
2019-08-01 03:58:42 +02:00
|
|
|
impl TaggedDictBuilder {
|
2019-08-05 10:54:29 +02:00
|
|
|
pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
|
2019-08-01 03:58:42 +02:00
|
|
|
TaggedDictBuilder {
|
2019-08-05 10:54:29 +02:00
|
|
|
tag: tag.into(),
|
2019-07-08 18:44:53 +02:00
|
|
|
dict: IndexMap::default(),
|
|
|
|
}
|
|
|
|
}
|
2019-09-03 02:49:51 +02:00
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn build(tag: impl Into<Tag>, block: impl FnOnce(&mut TaggedDictBuilder)) -> Value {
|
2019-11-04 16:47:03 +01:00
|
|
|
let mut builder = TaggedDictBuilder::new(tag);
|
|
|
|
block(&mut builder);
|
2019-11-21 15:33:14 +01:00
|
|
|
builder.into_value()
|
2019-11-04 16:47:03 +01:00
|
|
|
}
|
|
|
|
|
2019-08-28 17:53:59 +02:00
|
|
|
pub fn with_capacity(tag: impl Into<Tag>, n: usize) -> TaggedDictBuilder {
|
|
|
|
TaggedDictBuilder {
|
|
|
|
tag: tag.into(),
|
|
|
|
dict: IndexMap::with_capacity(n),
|
|
|
|
}
|
|
|
|
}
|
2019-07-08 18:44:53 +02:00
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn insert_untagged(&mut self, key: impl Into<String>, value: impl Into<UntaggedValue>) {
|
|
|
|
self.dict
|
|
|
|
.insert(key.into(), value.into().into_value(&self.tag));
|
2019-07-08 18:44:53 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn insert_value(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
2019-07-08 18:44:53 +02:00
|
|
|
self.dict.insert(key.into(), value.into());
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn into_value(self) -> Value {
|
|
|
|
let tag = self.tag.clone();
|
|
|
|
self.into_untagged_value().into_value(tag)
|
2019-07-09 06:31:26 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
pub fn into_untagged_value(self) -> UntaggedValue {
|
|
|
|
UntaggedValue::Row(Dictionary { entries: self.dict })
|
2019-07-08 18:44:53 +02:00
|
|
|
}
|
2019-09-16 09:52:58 +02:00
|
|
|
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.dict.is_empty()
|
|
|
|
}
|
2019-07-08 18:44:53 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
impl From<TaggedDictBuilder> for Value {
|
|
|
|
fn from(input: TaggedDictBuilder) -> Value {
|
|
|
|
input.into_value()
|
2019-07-08 18:44:53 +02:00
|
|
|
}
|
|
|
|
}
|