Ensure fields are not escaped when inserted as object keys

This commit is contained in:
Tobie Morgan Hitchcock 2022-05-31 20:44:27 +01:00
parent 3f568f3990
commit 4d9b3fd403
5 changed files with 49 additions and 9 deletions

View file

@ -43,6 +43,12 @@ impl Deref for Ident {
} }
} }
impl Ident {
pub fn to_raw(&self) -> String {
self.0.to_string()
}
}
impl fmt::Display for Ident { impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", escape_ident(&self.0)) write!(f, "{}", escape_ident(&self.0))

View file

@ -45,6 +45,12 @@ impl Deref for Idiom {
} }
} }
impl From<String> for Idiom {
fn from(v: String) -> Self {
Idiom(vec![Part::from(v)])
}
}
impl From<Vec<Part>> for Idiom { impl From<Vec<Part>> for Idiom {
fn from(v: Vec<Part>) -> Self { fn from(v: Vec<Part>) -> Self {
Idiom(v) Idiom(v)
@ -61,6 +67,15 @@ impl Idiom {
pub fn to_path(&self) -> String { pub fn to_path(&self) -> String {
format!("/{}", self).replace(']', "").replace(&['.', '['][..], "/") format!("/{}", self).replace(']', "").replace(&['.', '['][..], "/")
} }
///
pub fn simplify(&self) -> Idiom {
self.0
.iter()
.cloned()
.filter(|p| matches!(p, Part::Field(_) | Part::Graph(_)))
.collect::<Vec<_>>()
.into()
}
} }
impl Idiom { impl Idiom {

View file

@ -91,7 +91,7 @@ impl Object {
Some(o) => match self.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.jsonpath(),
value: match self.get("value") { value: match self.get("value") {
Some(v) => v.clone(), Some(v) => v.clone(),
None => Value::Null, None => Value::Null,

View file

@ -29,7 +29,7 @@ impl Value {
_ => { _ => {
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.to_string(), obj); v.insert(f.to_raw(), obj);
Ok(()) Ok(())
} }
}, },

View file

@ -639,13 +639,18 @@ impl Value {
} }
pub fn to_idiom(&self) -> Idiom { pub fn to_idiom(&self) -> Idiom {
self.to_strand() match self {
.as_str() Value::Idiom(v) => v.simplify(),
.trim_start_matches('/') Value::Strand(v) => v.0.to_string().into(),
.split(&['.', '/'][..]) Value::Datetime(v) => v.0.to_string().into(),
.map(Part::from) Value::Function(v) => match v.as_ref() {
.collect::<Vec<Part>>() Function::Future(_) => "fn::future".to_string().into(),
.into() Function::Script(_) => "fn::script".to_string().into(),
Function::Normal(f, _) => f.to_string().into(),
_ => v.to_string().into(),
},
_ => self.to_string().into(),
}
} }
// ----------------------------------- // -----------------------------------
@ -738,6 +743,20 @@ impl Value {
} }
} }
// -----------------------------------
// JSON Path conversion
// -----------------------------------
pub fn jsonpath(&self) -> Idiom {
self.to_strand()
.as_str()
.trim_start_matches('/')
.split(&['.', '/'][..])
.map(Part::from)
.collect::<Vec<Part>>()
.into()
}
// ----------------------------------- // -----------------------------------
// Value operations // Value operations
// ----------------------------------- // -----------------------------------