2019-05-15 22:58:44 +00:00
|
|
|
use crate::prelude::*;
|
2019-05-10 16:59:12 +00:00
|
|
|
use crate::object::{Primitive, Value};
|
2019-06-01 05:50:16 +00:00
|
|
|
use derive_new::new;
|
2019-05-15 18:14:51 +00:00
|
|
|
use indexmap::IndexMap;
|
2019-07-03 17:37:09 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2019-05-17 15:55:50 +00:00
|
|
|
use std::cmp::{Ordering, PartialOrd};
|
2019-06-22 03:43:37 +00:00
|
|
|
use std::fmt;
|
2019-05-10 16:59:12 +00:00
|
|
|
|
2019-07-03 17:37:09 +00:00
|
|
|
#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, new)]
|
2019-05-10 16:59:12 +00:00
|
|
|
pub struct Dictionary {
|
2019-08-01 01:58:42 +00:00
|
|
|
pub entries: IndexMap<String, Tagged<Value>>,
|
2019-05-10 16:59:12 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 15:55:50 +00:00
|
|
|
impl PartialOrd for Dictionary {
|
2019-06-24 00:55:31 +00:00
|
|
|
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
|
2019-07-03 17:37:09 +00:00
|
|
|
let this: Vec<&String> = self.entries.keys().collect();
|
|
|
|
let that: Vec<&String> = other.entries.keys().collect();
|
2019-06-24 00:55:31 +00:00
|
|
|
|
|
|
|
if this != that {
|
|
|
|
return this.partial_cmp(&that);
|
|
|
|
}
|
|
|
|
|
2019-07-09 04:31:26 +00: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 00:55:31 +00:00
|
|
|
|
|
|
|
this.partial_cmp(&that)
|
2019-05-17 15:55:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
impl From<IndexMap<String, Tagged<Value>>> for Dictionary {
|
|
|
|
fn from(input: IndexMap<String, Tagged<Value>>) -> Dictionary {
|
2019-06-01 05:50:16 +00:00
|
|
|
let mut out = IndexMap::default();
|
|
|
|
|
|
|
|
for (key, value) in input {
|
2019-07-03 17:37:09 +00:00
|
|
|
out.insert(key, value);
|
2019-06-01 05:50:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Dictionary::new(out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 15:55:50 +00:00
|
|
|
impl Ord for Dictionary {
|
2019-06-24 00:55:31 +00:00
|
|
|
fn cmp(&self, other: &Dictionary) -> Ordering {
|
2019-07-03 17:37:09 +00:00
|
|
|
let this: Vec<&String> = self.entries.keys().collect();
|
|
|
|
let that: Vec<&String> = other.entries.keys().collect();
|
2019-06-24 00:55:31 +00:00
|
|
|
|
|
|
|
if this != that {
|
|
|
|
return this.cmp(&that);
|
|
|
|
}
|
|
|
|
|
2019-07-09 04:31:26 +00: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 00:55:31 +00:00
|
|
|
|
|
|
|
this.cmp(&that)
|
2019-05-17 15:55:50 +00: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::Object(d) => self == d,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 16:59:12 +00:00
|
|
|
impl Dictionary {
|
2019-08-29 12:16:11 +00:00
|
|
|
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
2019-05-24 18:48:33 +00:00
|
|
|
match self.entries.get(desc) {
|
2019-05-15 18:14:51 +00:00
|
|
|
Some(v) => MaybeOwned::Borrowed(v),
|
2019-05-10 16:59:12 +00:00
|
|
|
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
|
|
|
}
|
|
|
|
}
|
2019-05-17 15:55:50 +00:00
|
|
|
|
2019-08-29 11:08:28 +00:00
|
|
|
pub(crate) fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
2019-05-24 18:48:33 +00:00
|
|
|
match self
|
|
|
|
.entries
|
|
|
|
.iter()
|
2019-07-03 17:37:09 +00:00
|
|
|
.find(|(desc_name, _)| *desc_name == name)
|
2019-05-24 18:48:33 +00:00
|
|
|
{
|
2019-05-28 06:45:18 +00:00
|
|
|
Some((_, v)) => Some(v),
|
|
|
|
None => None,
|
2019-05-17 15:55:50 +00:00
|
|
|
}
|
|
|
|
}
|
2019-06-22 03:43:37 +00:00
|
|
|
|
2019-08-29 11:08:28 +00:00
|
|
|
pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2019-06-22 03:43:37 +00:00
|
|
|
let mut debug = f.debug_struct("Dictionary");
|
|
|
|
|
|
|
|
for (desc, value) in self.entries.iter() {
|
2019-07-03 17:37:09 +00:00
|
|
|
debug.field(desc, &value.debug());
|
2019-06-22 03:43:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
debug.finish()
|
|
|
|
}
|
2019-05-10 16:59:12 +00:00
|
|
|
}
|
2019-07-08 16:44:53 +00:00
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub struct TaggedListBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
tag: Tag,
|
2019-08-01 01:58:42 +00:00
|
|
|
list: Vec<Tagged<Value>>,
|
2019-07-09 04:31:26 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
impl TaggedListBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
pub fn new(tag: impl Into<Tag>) -> TaggedListBuilder {
|
2019-08-01 01:58:42 +00:00
|
|
|
TaggedListBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
tag: tag.into(),
|
2019-07-09 04:31:26 +00:00
|
|
|
list: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push(&mut self, value: impl Into<Value>) {
|
2019-08-05 08:54:29 +00:00
|
|
|
self.list.push(value.into().tagged(self.tag));
|
2019-07-09 04:31:26 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) {
|
2019-07-09 04:31:26 +00:00
|
|
|
self.list.push(value.into());
|
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub fn into_tagged_value(self) -> Tagged<Value> {
|
2019-08-05 08:54:29 +00:00
|
|
|
Value::List(self.list).tagged(self.tag)
|
2019-07-09 04:31:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
impl From<TaggedListBuilder> for Tagged<Value> {
|
|
|
|
fn from(input: TaggedListBuilder) -> Tagged<Value> {
|
|
|
|
input.into_tagged_value()
|
2019-07-09 04:31:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-08 16:44:53 +00:00
|
|
|
#[derive(Debug)]
|
2019-08-01 01:58:42 +00:00
|
|
|
pub struct TaggedDictBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
tag: Tag,
|
2019-08-01 01:58:42 +00:00
|
|
|
dict: IndexMap<String, Tagged<Value>>,
|
2019-07-08 16:44:53 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
impl TaggedDictBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
|
2019-08-01 01:58:42 +00:00
|
|
|
TaggedDictBuilder {
|
2019-08-05 08:54:29 +00:00
|
|
|
tag: tag.into(),
|
2019-07-08 16:44:53 +00:00
|
|
|
dict: IndexMap::default(),
|
|
|
|
}
|
|
|
|
}
|
2019-08-28 15:53:59 +00:00
|
|
|
|
|
|
|
pub fn with_capacity(tag: impl Into<Tag>, n: usize) -> TaggedDictBuilder {
|
|
|
|
TaggedDictBuilder {
|
|
|
|
tag: tag.into(),
|
|
|
|
dict: IndexMap::with_capacity(n),
|
|
|
|
}
|
|
|
|
}
|
2019-07-08 16:44:53 +00:00
|
|
|
|
2019-07-13 02:07:06 +00:00
|
|
|
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
2019-08-05 08:54:29 +00:00
|
|
|
self.dict.insert(key.into(), value.into().tagged(self.tag));
|
2019-07-08 16:44:53 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) {
|
2019-07-08 16:44:53 +00:00
|
|
|
self.dict.insert(key.into(), value.into());
|
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub fn into_tagged_value(self) -> Tagged<Value> {
|
|
|
|
self.into_tagged_dict().map(Value::Object)
|
2019-07-09 04:31:26 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
pub fn into_tagged_dict(self) -> Tagged<Dictionary> {
|
2019-08-05 08:54:29 +00:00
|
|
|
Dictionary { entries: self.dict }.tagged(self.tag)
|
2019-07-08 16:44:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 01:58:42 +00:00
|
|
|
impl From<TaggedDictBuilder> for Tagged<Value> {
|
|
|
|
fn from(input: TaggedDictBuilder) -> Tagged<Value> {
|
|
|
|
input.into_tagged_value()
|
2019-07-08 16:44:53 +00:00
|
|
|
}
|
|
|
|
}
|