nushell/src/data/dict.rs

255 lines
6.9 KiB
Rust
Raw Normal View History

use crate::data::{Primitive, Value};
2019-05-16 00:58:44 +02:00
use crate::prelude::*;
2019-11-04 16:47:03 +01:00
use crate::traits::{DebugDocBuilder as b, PrettyDebug};
use derive_new::new;
2019-11-04 16:47:03 +01:00
use getset::Getters;
use indexmap::IndexMap;
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-08-01 03:58:42 +02:00
pub entries: IndexMap<String, Tagged<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,
value: &'a Tagged<Value>,
}
impl<'a> PrettyDebug for DebugEntry<'a> {
fn pretty_debug(&self) -> DebugDocBuilder {
(b::key(self.key.to_string()) + b::equals() + self.value.item.pretty_debug().as_value())
.group()
// BoxAllocator
// .text(self.key.to_string())
// .annotate(ShellAnnotation::style("key"))
// .append(
// BoxAllocator
// .text("=")
// .annotate(ShellAnnotation::style("equals")),
// )
// .append({
// self.value
// .item
// .pretty_debug()
// .inner
// .annotate(ShellAnnotation::style("value"))
// })
// .group()
// .into()
}
}
impl PrettyDebug for Dictionary {
fn pretty_debug(&self) -> DebugDocBuilder {
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-07-09 06:31:26 +02:00
let this: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
let that: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
2019-06-24 02:55:31 +02:00
this.partial_cmp(&that)
2019-05-17 17:55:50 +02:00
}
}
2019-08-01 03:58:42 +02:00
impl From<IndexMap<String, Tagged<Value>>> for Dictionary {
fn from(input: IndexMap<String, Tagged<Value>>) -> Dictionary {
let mut out = IndexMap::default();
for (key, value) in input {
2019-07-03 19:37:09 +02:00
out.insert(key, value);
}
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-07-09 06:31:26 +02:00
let this: Vec<&Value> = self.entries.values().map(|v| v.item()).collect();
let that: Vec<&Value> = self.entries.values().map(|v| v.item()).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 {
match other {
Value::Row(d) => self == d,
2019-05-17 17:55:50 +02:00
_ => false,
}
}
}
2019-05-10 18:59:12 +02:00
impl Dictionary {
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
match self.entries.get(desc) {
Some(v) => MaybeOwned::Borrowed(v),
2019-05-10 18:59:12 +02:00
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
}
}
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()
}
pub(crate) fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Tagged<Value>> {
let result = self
.entries
.iter()
2019-11-04 16:47:03 +01:00
.find(|(desc_name, _)| *desc_name == name.item)?
.1;
Some(
result
.item
.clone()
.tagged(Tag::new(result.anchor(), name.span)),
)
2019-05-17 17:55:50 +02:00
}
2019-06-22 05:43:37 +02:00
pub(crate) fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Tagged<Value>> {
match self
.entries
.iter_mut()
.find(|(desc_name, _)| *desc_name == name)
{
Some((_, v)) => Some(v),
None => None,
}
}
2019-11-04 16:47:03 +01:00
pub(crate) fn insert_data_at_key(&mut self, name: &str, value: Tagged<Value>) {
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 {
tag: Tag,
2019-11-12 08:07:43 +01:00
pub list: Vec<Tagged<Value>>,
2019-07-09 06:31:26 +02:00
}
2019-08-01 03:58:42 +02:00
impl TaggedListBuilder {
pub fn new(tag: impl Into<Tag>) -> TaggedListBuilder {
2019-08-01 03:58:42 +02:00
TaggedListBuilder {
tag: tag.into(),
2019-07-09 06:31:26 +02:00
list: vec![],
}
}
pub fn push(&mut self, value: impl Into<Value>) {
self.list.push(value.into().tagged(&self.tag));
2019-07-09 06:31:26 +02:00
}
2019-08-01 03:58:42 +02:00
pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) {
2019-07-09 06:31:26 +02:00
self.list.push(value.into());
}
2019-08-01 03:58:42 +02:00
pub fn into_tagged_value(self) -> Tagged<Value> {
Value::Table(self.list).tagged(self.tag)
2019-07-09 06:31:26 +02:00
}
}
2019-08-01 03:58:42 +02:00
impl From<TaggedListBuilder> for Tagged<Value> {
fn from(input: TaggedListBuilder) -> Tagged<Value> {
input.into_tagged_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 {
tag: Tag,
2019-08-01 03:58:42 +02:00
dict: IndexMap<String, Tagged<Value>>,
2019-07-08 18:44:53 +02:00
}
2019-08-01 03:58:42 +02:00
impl TaggedDictBuilder {
pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
2019-08-01 03:58:42 +02:00
TaggedDictBuilder {
tag: tag.into(),
2019-07-08 18:44:53 +02:00
dict: IndexMap::default(),
}
}
2019-11-04 16:47:03 +01:00
pub fn build(tag: impl Into<Tag>, block: impl FnOnce(&mut TaggedDictBuilder)) -> Tagged<Value> {
let mut builder = TaggedDictBuilder::new(tag);
block(&mut builder);
builder.into_tagged_value()
}
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-07-13 04:07:06 +02:00
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
self.dict.insert(key.into(), value.into().tagged(&self.tag));
2019-07-08 18:44:53 +02:00
}
2019-08-01 03:58:42 +02:00
pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) {
2019-07-08 18:44:53 +02:00
self.dict.insert(key.into(), value.into());
}
2019-08-01 03:58:42 +02:00
pub fn into_tagged_value(self) -> Tagged<Value> {
self.into_tagged_dict().map(Value::Row)
2019-07-09 06:31:26 +02:00
}
2019-08-01 03:58:42 +02:00
pub fn into_tagged_dict(self) -> Tagged<Dictionary> {
Dictionary { entries: self.dict }.tagged(self.tag)
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-08-01 03:58:42 +02:00
impl From<TaggedDictBuilder> for Tagged<Value> {
fn from(input: TaggedDictBuilder) -> Tagged<Value> {
input.into_tagged_value()
2019-07-08 18:44:53 +02:00
}
}