Add ‘every’ function on a value for field iteration

This commit is contained in:
Tobie Morgan Hitchcock 2022-04-07 11:12:48 +01:00
parent 9becf187f4
commit e378105f11
4 changed files with 66 additions and 1 deletions

View file

@ -31,6 +31,14 @@ impl<'a> From<&'a str> for Ident {
} }
} }
impl<'a> From<&'a String> for Ident {
fn from(i: &String) -> Ident {
Ident {
name: String::from(i),
}
}
}
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(&self.name, &val_char, "`")) write!(f, "{}", escape(&self.name, &val_char, "`"))

View file

@ -71,11 +71,17 @@ impl From<String> for Part {
} }
} }
impl From<&String> for Part {
fn from(v: &String) -> Self {
Part::Field(Ident::from(v))
}
}
impl From<&str> for Part { impl From<&str> for Part {
fn from(v: &str) -> Self { fn from(v: &str) -> Self {
match v.parse::<isize>() { match v.parse::<isize>() {
Ok(v) => Part::from(v), Ok(v) => Part::from(v),
_ => Part::from(v.to_string()), _ => Part::from(v.to_owned()),
} }
} }
} }

View file

@ -0,0 +1,50 @@
use crate::sql::idiom::Idiom;
use crate::sql::part::Part;
use crate::sql::value::Value;
impl Value {
pub fn every(&self) -> Vec<Idiom> {
self._every(Idiom::default())
}
fn _every(&self, prev: Idiom) -> Vec<Idiom> {
match self {
// Current path part is an object
Value::Object(v) => v
.value
.iter()
.flat_map(|(k, v)| v._every(prev.add(Part::from(k))))
.collect::<Vec<_>>(),
// Current path part is an array
Value::Array(v) => v
.value
.iter()
.enumerate()
.flat_map(|(i, v)| v._every(prev.add(Part::from(i))))
.collect::<Vec<_>>(),
// Process everything else
_ => vec![prev],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sql::idiom::Idiom;
use crate::sql::test::Parse;
#[test]
fn every() {
let val = Value::parse("{ test: { something: [{ age: 34, tags: ['code', 'databases'] }, { age: 36, tags: ['design', 'operations'] }] } }");
let res = vec![
Idiom::parse("test.something[0].age"),
Idiom::parse("test.something[0].tags[0]"),
Idiom::parse("test.something[0].tags[1]"),
Idiom::parse("test.something[1].age"),
Idiom::parse("test.something[1].tags[0]"),
Idiom::parse("test.something[1].tags[1]"),
];
assert_eq!(res, val.every());
}
}

View file

@ -9,6 +9,7 @@ mod def;
mod del; mod del;
mod diff; mod diff;
mod each; mod each;
mod every;
mod first; mod first;
mod get; mod get;
mod increment; mod increment;