Implement SQL Object as a newtype tuple struct
This commit is contained in:
parent
5182359813
commit
3ee1ddb5b1
12 changed files with 88 additions and 91 deletions
|
@ -15,65 +15,73 @@ use nom::combinator::opt;
|
||||||
use nom::multi::separated_list0;
|
use nom::multi::separated_list0;
|
||||||
use nom::sequence::delimited;
|
use nom::sequence::delimited;
|
||||||
use serde::ser::SerializeMap;
|
use serde::ser::SerializeMap;
|
||||||
use serde::ser::SerializeStruct;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)]
|
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)]
|
||||||
pub struct Object {
|
pub struct Object(pub BTreeMap<String, Value>);
|
||||||
pub value: BTreeMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BTreeMap<String, Value>> for Object {
|
impl From<BTreeMap<String, Value>> for Object {
|
||||||
fn from(v: BTreeMap<String, Value>) -> Self {
|
fn from(v: BTreeMap<String, Value>) -> Self {
|
||||||
Object {
|
Object(v)
|
||||||
value: v,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HashMap<String, Value>> for Object {
|
impl From<HashMap<String, Value>> for Object {
|
||||||
fn from(v: HashMap<String, Value>) -> Self {
|
fn from(v: HashMap<String, Value>) -> Self {
|
||||||
Object {
|
Object(v.into_iter().collect())
|
||||||
value: v.into_iter().collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Operation> for Object {
|
impl From<Operation> for Object {
|
||||||
fn from(v: Operation) -> Self {
|
fn from(v: Operation) -> Self {
|
||||||
Object {
|
Object(map! {
|
||||||
value: map! {
|
String::from("op") => match v.op {
|
||||||
String::from("op") => match v.op {
|
Op::None => Value::from("none"),
|
||||||
Op::None => Value::from("none"),
|
Op::Add => Value::from("add"),
|
||||||
Op::Add => Value::from("add"),
|
Op::Remove => Value::from("remove"),
|
||||||
Op::Remove => Value::from("remove"),
|
Op::Replace => Value::from("replace"),
|
||||||
Op::Replace => Value::from("replace"),
|
Op::Change => Value::from("change"),
|
||||||
Op::Change => Value::from("change"),
|
|
||||||
},
|
|
||||||
String::from("path") => v.path.to_path().into(),
|
|
||||||
String::from("value") => v.value,
|
|
||||||
},
|
},
|
||||||
}
|
String::from("path") => v.path.to_path().into(),
|
||||||
|
String::from("value") => v.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Object {
|
||||||
|
type Target = BTreeMap<String, Value>;
|
||||||
|
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<String, Value>;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Object {
|
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<Operation, Error> {
|
pub fn to_operation(&self) -> Result<Operation, Error> {
|
||||||
match self.value.get("op") {
|
match self.get("op") {
|
||||||
Some(o) => match self.value.get("path") {
|
Some(o) => match self.get("path") {
|
||||||
Some(p) => Ok(Operation {
|
Some(p) => Ok(Operation {
|
||||||
op: o.into(),
|
op: o.into(),
|
||||||
path: p.to_idiom(),
|
path: p.to_idiom(),
|
||||||
value: match self.value.get("value") {
|
value: match self.get("value") {
|
||||||
Some(v) => v.clone(),
|
Some(v) => v.clone(),
|
||||||
None => Value::Null,
|
None => Value::Null,
|
||||||
},
|
},
|
||||||
|
@ -98,15 +106,13 @@ impl Object {
|
||||||
doc: Option<&Value>,
|
doc: Option<&Value>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
let mut x = BTreeMap::new();
|
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 {
|
match v.compute(ctx, opt, txn, doc).await {
|
||||||
Ok(v) => x.insert(k.clone(), v),
|
Ok(v) => x.insert(k.clone(), v),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(Value::Object(Object {
|
Ok(Value::Object(Object(x)))
|
||||||
value: x,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +121,7 @@ impl fmt::Display for Object {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{{ {} }}",
|
"{{ {} }}",
|
||||||
self.value
|
self.iter()
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| format!("{}: {}", escape(k, &val_char, "\""), v))
|
.map(|(k, v)| format!("{}: {}", escape(k, &val_char, "\""), v))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
|
@ -130,16 +135,14 @@ impl Serialize for Object {
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
if serializer.is_human_readable() {
|
if serializer.is_human_readable() {
|
||||||
let mut map = serializer.serialize_map(Some(self.value.len()))?;
|
let mut map = serializer.serialize_map(Some(self.len()))?;
|
||||||
for (ref k, ref v) in &self.value {
|
for (ref k, ref v) in &self.0 {
|
||||||
map.serialize_key(k)?;
|
map.serialize_key(k)?;
|
||||||
map.serialize_value(v)?;
|
map.serialize_value(v)?;
|
||||||
}
|
}
|
||||||
map.end()
|
map.end()
|
||||||
} else {
|
} else {
|
||||||
let mut val = serializer.serialize_struct("Object", 1)?;
|
serializer.serialize_newtype_struct("Object", &self.0)
|
||||||
val.serialize_field("value", &self.value)?;
|
|
||||||
val.end()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,12 +155,7 @@ pub fn object(i: &str) -> IResult<&str, Object> {
|
||||||
let (i, _) = opt(char(','))(i)?;
|
let (i, _) = opt(char(','))(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, _) = char('}')(i)?;
|
let (i, _) = char('}')(i)?;
|
||||||
Ok((
|
Ok((i, Object(v.into_iter().collect())))
|
||||||
i,
|
|
||||||
Object {
|
|
||||||
value: v.into_iter().collect(),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item(i: &str) -> IResult<&str, (String, Value)> {
|
fn item(i: &str) -> IResult<&str, (String, Value)> {
|
||||||
|
@ -197,7 +195,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out));
|
assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out));
|
||||||
assert_eq!(out.value.len(), 3);
|
assert_eq!(out.0.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -207,7 +205,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out));
|
assert_eq!("{ one: 1, tre: 3, two: 2 }", format!("{}", out));
|
||||||
assert_eq!(out.value.len(), 3);
|
assert_eq!(out.0.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -217,6 +215,6 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("{ one: 1, tre: 3 + 1, two: 2 }", format!("{}", out));
|
assert_eq!("{ one: 1, tre: 3 + 1, two: 2 }", format!("{}", out));
|
||||||
assert_eq!(out.value.len(), 3);
|
assert_eq!(out.0.len(), 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@ impl InfoStatement {
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_ns().await? {
|
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
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -63,21 +63,21 @@ impl InfoStatement {
|
||||||
// Process the databases
|
// Process the databases
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_db(opt.ns()).await? {
|
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
|
// Process the tokens
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_nt(opt.ns()).await? {
|
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
|
// Process the logins
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_nl(opt.ns()).await? {
|
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
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -93,27 +93,27 @@ impl InfoStatement {
|
||||||
// Process the tables
|
// Process the tables
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_tb(opt.ns(), opt.db()).await? {
|
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
|
// Process the scopes
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_sc(opt.ns(), opt.db()).await? {
|
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
|
// Process the tokens
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_nt(opt.ns()).await? {
|
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
|
// Process the logins
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_nl(opt.ns()).await? {
|
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
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -129,9 +129,9 @@ impl InfoStatement {
|
||||||
// Process the tokens
|
// Process the tokens
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_st(opt.ns(), opt.db(), sc).await? {
|
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
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -147,27 +147,27 @@ impl InfoStatement {
|
||||||
// Process the events
|
// Process the events
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_ev(opt.ns(), opt.db(), tb).await? {
|
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
|
// Process the fields
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_fd(opt.ns(), opt.db(), tb).await? {
|
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
|
// Process the indexs
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_ix(opt.ns(), opt.db(), tb).await? {
|
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
|
// Process the tables
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_ft(opt.ns(), opt.db(), tb).await? {
|
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
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl Value {
|
||||||
Some(p) => match (self, other) {
|
Some(p) => match (self, other) {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
(Value::Object(a), Value::Object(b)) => match p {
|
(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(a), Some(b)) => a.compare(b, path.next(), collate, numeric),
|
||||||
(Some(_), None) => Some(Ordering::Greater),
|
(Some(_), None) => Some(Ordering::Greater),
|
||||||
(None, Some(_)) => Some(Ordering::Less),
|
(None, Some(_)) => Some(Ordering::Less),
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl Value {
|
||||||
v.remove(&f.name);
|
v.remove(&f.name);
|
||||||
Ok(())
|
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,
|
Some(v) if v.is_some() => v.del(ctx, opt, txn, path.next()).await,
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,8 +9,8 @@ impl Value {
|
||||||
match (self, val) {
|
match (self, val) {
|
||||||
(Value::Object(a), Value::Object(b)) if a != b => {
|
(Value::Object(a), Value::Object(b)) if a != b => {
|
||||||
// Loop over old keys
|
// Loop over old keys
|
||||||
for (key, _) in a.value.iter() {
|
for (key, _) in a.iter() {
|
||||||
if !b.value.contains_key(key) {
|
if !b.contains_key(key) {
|
||||||
ops.push(Operation {
|
ops.push(Operation {
|
||||||
op: Op::Remove,
|
op: Op::Remove,
|
||||||
path: path.clone().push(key.clone().into()),
|
path: path.clone().push(key.clone().into()),
|
||||||
|
@ -19,8 +19,8 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loop over new keys
|
// Loop over new keys
|
||||||
for (key, val) in b.value.iter() {
|
for (key, val) in b.iter() {
|
||||||
match a.value.get(key) {
|
match a.get(key) {
|
||||||
None => ops.push(Operation {
|
None => ops.push(Operation {
|
||||||
op: Op::Add,
|
op: Op::Add,
|
||||||
path: path.clone().push(key.clone().into()),
|
path: path.clone().push(key.clone().into()),
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
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())),
|
Some(v) => v._each(path.next(), prev.push(p.clone())),
|
||||||
None => vec![],
|
None => vec![],
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,7 +10,6 @@ impl Value {
|
||||||
match self {
|
match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => v
|
Value::Object(v) => v
|
||||||
.value
|
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(k, v)| v._every(prev.clone().push(Part::from(k))))
|
.flat_map(|(k, v)| v._every(prev.clone().push(Part::from(k))))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
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,
|
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||||
None => Ok(Value::None),
|
None => Ok(Value::None),
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl Value {
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match val.compute(ctx, opt, txn, Some(self)).await? {
|
match val.compute(ctx, opt, txn, Some(self)).await? {
|
||||||
Value::Object(v) => {
|
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?;
|
self.set(ctx, opt, txn, &[Part::from(k)], v).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -9,7 +9,7 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
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()),
|
Some(v) => v.pick(path.next()),
|
||||||
None => Value::None,
|
None => Value::None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,12 +24,12 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
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,
|
Some(v) if v.is_some() => v.set(ctx, opt, txn, path.next(), val).await,
|
||||||
_ => {
|
_ => {
|
||||||
let mut obj = Value::base();
|
let mut obj = Value::base();
|
||||||
obj.set(ctx, opt, txn, path.next(), val).await?;
|
obj.set(ctx, opt, txn, path.next(), val).await?;
|
||||||
v.insert(&f.name, obj);
|
v.insert(f.name.to_owned(), obj);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -499,7 +499,7 @@ impl Value {
|
||||||
Value::Thing(_) => true,
|
Value::Thing(_) => true,
|
||||||
Value::Geometry(_) => true,
|
Value::Geometry(_) => true,
|
||||||
Value::Array(v) => !v.value.is_empty(),
|
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::Strand(v) => !v.value.is_empty() && v.value.to_ascii_lowercase() != "false",
|
||||||
Value::Number(v) => v.is_truthy(),
|
Value::Number(v) => v.is_truthy(),
|
||||||
Value::Duration(v) => v.value.as_nanos() > 0,
|
Value::Duration(v) => v.value.as_nanos() > 0,
|
||||||
|
|
Loading…
Reference in a new issue