diff --git a/lib/src/sql/object.rs b/lib/src/sql/object.rs index 50a0acc6..347c98cf 100644 --- a/lib/src/sql/object.rs +++ b/lib/src/sql/object.rs @@ -15,65 +15,73 @@ use nom::combinator::opt; use nom::multi::separated_list0; use nom::sequence::delimited; use serde::ser::SerializeMap; -use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::collections::HashMap; use std::fmt; +use std::ops::Deref; +use std::ops::DerefMut; #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)] -pub struct Object { - pub value: BTreeMap, -} +pub struct Object(pub BTreeMap); impl From> for Object { fn from(v: BTreeMap) -> Self { - Object { - value: v, - } + Object(v) } } impl From> for Object { fn from(v: HashMap) -> Self { - Object { - value: v.into_iter().collect(), - } + Object(v.into_iter().collect()) } } impl From for Object { fn from(v: Operation) -> Self { - Object { - value: map! { - String::from("op") => match v.op { - Op::None => Value::from("none"), - Op::Add => Value::from("add"), - Op::Remove => Value::from("remove"), - Op::Replace => Value::from("replace"), - Op::Change => Value::from("change"), - }, - String::from("path") => v.path.to_path().into(), - String::from("value") => v.value, + Object(map! { + String::from("op") => match v.op { + Op::None => Value::from("none"), + Op::Add => Value::from("add"), + Op::Remove => Value::from("remove"), + Op::Replace => Value::from("replace"), + Op::Change => Value::from("change"), }, - } + String::from("path") => v.path.to_path().into(), + String::from("value") => v.value, + }) + } +} + +impl Deref for Object { + type Target = BTreeMap; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Object { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl IntoIterator for Object { + type Item = (String, Value); + type IntoIter = std::collections::btree_map::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() } } impl Object { - pub fn remove(&mut self, key: &str) { - self.value.remove(key); - } - pub fn insert(&mut self, key: &str, val: Value) { - self.value.insert(key.to_owned(), val); - } pub fn to_operation(&self) -> Result { - match self.value.get("op") { - Some(o) => match self.value.get("path") { + match self.get("op") { + Some(o) => match self.get("path") { Some(p) => Ok(Operation { op: o.into(), path: p.to_idiom(), - value: match self.value.get("value") { + value: match self.get("value") { Some(v) => v.clone(), None => Value::Null, }, @@ -98,15 +106,13 @@ impl Object { doc: Option<&Value>, ) -> Result { let mut x = BTreeMap::new(); - for (k, v) in &self.value { + for (k, v) in self.iter() { match v.compute(ctx, opt, txn, doc).await { Ok(v) => x.insert(k.clone(), v), Err(e) => return Err(e), }; } - Ok(Value::Object(Object { - value: x, - })) + Ok(Value::Object(Object(x))) } } @@ -115,8 +121,7 @@ impl fmt::Display for Object { write!( f, "{{ {} }}", - self.value - .iter() + self.iter() .map(|(k, v)| format!("{}: {}", escape(k, &val_char, "\""), v)) .collect::>() .join(", ") @@ -130,16 +135,14 @@ impl Serialize for Object { S: serde::Serializer, { if serializer.is_human_readable() { - let mut map = serializer.serialize_map(Some(self.value.len()))?; - for (ref k, ref v) in &self.value { + let mut map = serializer.serialize_map(Some(self.len()))?; + for (ref k, ref v) in &self.0 { map.serialize_key(k)?; map.serialize_value(v)?; } map.end() } else { - let mut val = serializer.serialize_struct("Object", 1)?; - val.serialize_field("value", &self.value)?; - val.end() + serializer.serialize_newtype_struct("Object", &self.0) } } } @@ -152,12 +155,7 @@ pub fn object(i: &str) -> IResult<&str, Object> { let (i, _) = opt(char(','))(i)?; let (i, _) = mightbespace(i)?; let (i, _) = char('}')(i)?; - Ok(( - i, - Object { - value: v.into_iter().collect(), - }, - )) + Ok((i, Object(v.into_iter().collect()))) } fn item(i: &str) -> IResult<&str, (String, Value)> { @@ -197,7 +195,7 @@ mod tests { assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out)); - assert_eq!(out.value.len(), 3); + assert_eq!(out.0.len(), 3); } #[test] @@ -207,7 +205,7 @@ mod tests { assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out)); - assert_eq!(out.value.len(), 3); + assert_eq!(out.0.len(), 3); } #[test] @@ -217,6 +215,6 @@ mod tests { assert!(res.is_ok()); let out = res.unwrap().1; assert_eq!("{ one: 1, tre: 3 + 1, two: 2 }", format!("{}", out)); - assert_eq!(out.value.len(), 3); + assert_eq!(out.0.len(), 3); } } diff --git a/lib/src/sql/statements/info.rs b/lib/src/sql/statements/info.rs index 6941fa78..95ea8585 100644 --- a/lib/src/sql/statements/info.rs +++ b/lib/src/sql/statements/info.rs @@ -45,9 +45,9 @@ impl InfoStatement { // Process the statement let mut tmp = Object::default(); for v in run.all_ns().await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("ns", tmp.into()); + res.insert("ns".to_owned(), tmp.into()); // Ok all good Value::from(res).ok() } @@ -63,21 +63,21 @@ impl InfoStatement { // Process the databases let mut tmp = Object::default(); for v in run.all_db(opt.ns()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("db", tmp.into()); + res.insert("db".to_owned(), tmp.into()); // Process the tokens let mut tmp = Object::default(); for v in run.all_nt(opt.ns()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("nt", tmp.into()); + res.insert("nt".to_owned(), tmp.into()); // Process the logins let mut tmp = Object::default(); for v in run.all_nl(opt.ns()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("nl", tmp.into()); + res.insert("nl".to_owned(), tmp.into()); // Ok all good Value::from(res).ok() } @@ -93,27 +93,27 @@ impl InfoStatement { // Process the tables let mut tmp = Object::default(); for v in run.all_tb(opt.ns(), opt.db()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("tb", tmp.into()); + res.insert("tb".to_owned(), tmp.into()); // Process the scopes let mut tmp = Object::default(); for v in run.all_sc(opt.ns(), opt.db()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("sc", tmp.into()); + res.insert("sc".to_owned(), tmp.into()); // Process the tokens let mut tmp = Object::default(); for v in run.all_nt(opt.ns()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("nt", tmp.into()); + res.insert("nt".to_owned(), tmp.into()); // Process the logins let mut tmp = Object::default(); for v in run.all_nl(opt.ns()).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("nl", tmp.into()); + res.insert("nl".to_owned(), tmp.into()); // Ok all good Value::from(res).ok() } @@ -129,9 +129,9 @@ impl InfoStatement { // Process the tokens let mut tmp = Object::default(); for v in run.all_st(opt.ns(), opt.db(), sc).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("st", tmp.into()); + res.insert("st".to_owned(), tmp.into()); // Ok all good Value::from(res).ok() } @@ -147,27 +147,27 @@ impl InfoStatement { // Process the events let mut tmp = Object::default(); for v in run.all_ev(opt.ns(), opt.db(), tb).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("ev", tmp.into()); + res.insert("ev".to_owned(), tmp.into()); // Process the fields let mut tmp = Object::default(); for v in run.all_fd(opt.ns(), opt.db(), tb).await? { - tmp.insert(&v.name.to_string(), v.to_string().into()); + tmp.insert(v.name.to_string(), v.to_string().into()); } - res.insert("fd", tmp.into()); + res.insert("fd".to_owned(), tmp.into()); // Process the indexs let mut tmp = Object::default(); for v in run.all_ix(opt.ns(), opt.db(), tb).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("ix", tmp.into()); + res.insert("ix".to_owned(), tmp.into()); // Process the tables let mut tmp = Object::default(); for v in run.all_ft(opt.ns(), opt.db(), tb).await? { - tmp.insert(&v.name, v.to_string().into()); + tmp.insert(v.name.to_owned(), v.to_string().into()); } - res.insert("ft", tmp.into()); + res.insert("ft".to_owned(), tmp.into()); // Ok all good Value::from(res).ok() } diff --git a/lib/src/sql/value/compare.rs b/lib/src/sql/value/compare.rs index 0dec7568..1690f1df 100644 --- a/lib/src/sql/value/compare.rs +++ b/lib/src/sql/value/compare.rs @@ -16,7 +16,7 @@ impl Value { Some(p) => match (self, other) { // Current path part is an object (Value::Object(a), Value::Object(b)) => match p { - Part::Field(f) => match (a.value.get(&f.name), b.value.get(&f.name)) { + Part::Field(f) => match (a.get(&f.name), b.get(&f.name)) { (Some(a), Some(b)) => a.compare(b, path.next(), collate, numeric), (Some(_), None) => Some(Ordering::Greater), (None, Some(_)) => Some(Ordering::Less), diff --git a/lib/src/sql/value/del.rs b/lib/src/sql/value/del.rs index 1796bb26..29c68e5a 100644 --- a/lib/src/sql/value/del.rs +++ b/lib/src/sql/value/del.rs @@ -30,7 +30,7 @@ impl Value { v.remove(&f.name); Ok(()) } - _ => match v.value.get_mut(&f.name) { + _ => match v.get_mut(&f.name) { Some(v) if v.is_some() => v.del(ctx, opt, txn, path.next()).await, _ => Ok(()), }, diff --git a/lib/src/sql/value/diff.rs b/lib/src/sql/value/diff.rs index 65c0806b..238efdba 100644 --- a/lib/src/sql/value/diff.rs +++ b/lib/src/sql/value/diff.rs @@ -9,8 +9,8 @@ impl Value { match (self, val) { (Value::Object(a), Value::Object(b)) if a != b => { // Loop over old keys - for (key, _) in a.value.iter() { - if !b.value.contains_key(key) { + for (key, _) in a.iter() { + if !b.contains_key(key) { ops.push(Operation { op: Op::Remove, path: path.clone().push(key.clone().into()), @@ -19,8 +19,8 @@ impl Value { } } // Loop over new keys - for (key, val) in b.value.iter() { - match a.value.get(key) { + for (key, val) in b.iter() { + match a.get(key) { None => ops.push(Operation { op: Op::Add, path: path.clone().push(key.clone().into()), diff --git a/lib/src/sql/value/each.rs b/lib/src/sql/value/each.rs index 64b0c13b..60792a1c 100644 --- a/lib/src/sql/value/each.rs +++ b/lib/src/sql/value/each.rs @@ -13,7 +13,7 @@ impl Value { Some(p) => match self { // Current path part is an object Value::Object(v) => match p { - Part::Field(f) => match v.value.get(&f.name) { + Part::Field(f) => match v.get(&f.name) { Some(v) => v._each(path.next(), prev.push(p.clone())), None => vec![], }, diff --git a/lib/src/sql/value/every.rs b/lib/src/sql/value/every.rs index 7db80bd4..c222ec06 100644 --- a/lib/src/sql/value/every.rs +++ b/lib/src/sql/value/every.rs @@ -10,7 +10,6 @@ impl Value { match self { // Current path part is an object Value::Object(v) => v - .value .iter() .flat_map(|(k, v)| v._every(prev.clone().push(Part::from(k)))) .collect::>(), diff --git a/lib/src/sql/value/get.rs b/lib/src/sql/value/get.rs index e51d3a63..dbd20a6e 100644 --- a/lib/src/sql/value/get.rs +++ b/lib/src/sql/value/get.rs @@ -26,7 +26,7 @@ impl Value { Some(p) => match self { // Current path part is an object Value::Object(v) => match p { - Part::Field(f) => match v.value.get(&f.name) { + Part::Field(f) => match v.get(&f.name) { Some(v) => v.get(ctx, opt, txn, path.next()).await, None => Ok(Value::None), }, diff --git a/lib/src/sql/value/merge.rs b/lib/src/sql/value/merge.rs index cdeeeb1f..48655c5b 100644 --- a/lib/src/sql/value/merge.rs +++ b/lib/src/sql/value/merge.rs @@ -15,7 +15,7 @@ impl Value { ) -> Result<(), Error> { match val.compute(ctx, opt, txn, Some(self)).await? { Value::Object(v) => { - for (k, v) in v.value.into_iter() { + for (k, v) in v { self.set(ctx, opt, txn, &[Part::from(k)], v).await?; } Ok(()) diff --git a/lib/src/sql/value/pick.rs b/lib/src/sql/value/pick.rs index d836749b..ca9f35b8 100644 --- a/lib/src/sql/value/pick.rs +++ b/lib/src/sql/value/pick.rs @@ -9,7 +9,7 @@ impl Value { Some(p) => match self { // Current path part is an object Value::Object(v) => match p { - Part::Field(f) => match v.value.get(&f.name) { + Part::Field(f) => match v.get(&f.name) { Some(v) => v.pick(path.next()), None => Value::None, }, diff --git a/lib/src/sql/value/set.rs b/lib/src/sql/value/set.rs index 22e36372..2e3f5b28 100644 --- a/lib/src/sql/value/set.rs +++ b/lib/src/sql/value/set.rs @@ -24,12 +24,12 @@ impl Value { Some(p) => match self { // Current path part is an object Value::Object(v) => match p { - Part::Field(f) => match v.value.get_mut(&f.name) { + Part::Field(f) => match v.get_mut(&f.name) { Some(v) if v.is_some() => v.set(ctx, opt, txn, path.next(), val).await, _ => { let mut obj = Value::base(); obj.set(ctx, opt, txn, path.next(), val).await?; - v.insert(&f.name, obj); + v.insert(f.name.to_owned(), obj); Ok(()) } }, diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 8199bfe8..7c822fc1 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -499,7 +499,7 @@ impl Value { Value::Thing(_) => true, Value::Geometry(_) => true, Value::Array(v) => !v.value.is_empty(), - Value::Object(v) => !v.value.is_empty(), + Value::Object(v) => !v.is_empty(), Value::Strand(v) => !v.value.is_empty() && v.value.to_ascii_lowercase() != "false", Value::Number(v) => v.is_truthy(), Value::Duration(v) => v.value.as_nanos() > 0,