Skip to content

Commit

Permalink
Chore/keys (#283)
Browse files Browse the repository at this point in the history
* chore(state): save current changes

* fix(parser+docs): adjust code, add documentation
  • Loading branch information
yamafaktory authored Oct 28, 2024
1 parent 05eed26 commit 43393c5
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 38 deletions.
54 changes: 27 additions & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ members = [
]

[workspace.dependencies]
thiserror = "1.0.64"
serde_json = { features = ["preserve_order", "unbounded_depth"], version = "1.0.128" }
thiserror = "1.0.65"
serde_json = { features = ["preserve_order", "unbounded_depth"], version = "1.0.132" }

[workspace.package]
authors = ["Davy Duperron <yamafaktory@gmail.com>"]
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,28 @@ Flattens arrays and objects.
}
```

##### Keys operator

Returns the keys of an object or the indices of an array. Other primitives are returned as is.

**JSON input**

```json
{ "a": 1, "b": 2, "c": 3 }
```

**Query**

```sh
'@'
```

**JSON output**

```json
["a", "b", "c"]
```

##### Pipe in operator

Applies the next tokens in parallel on each element of an array.
Expand Down
2 changes: 1 addition & 1 deletion crates/jql-parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ version.workspace = true

[dependencies]
thiserror.workspace = true
winnow = { version = "0.6.18", features = ["simd"] }
winnow = { version = "0.6.20", features = ["simd"] }

[lib]
path = "src/lib.rs"
15 changes: 15 additions & 0 deletions crates/jql-parser/src/combinators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static TRUE: &str = "true";
/// Lenses start.
static LENSES_START: &str = "|={";

/// Keys operator.
static KEYS: &str = "@";
/// Flatten operator.
static FLATTEN: &str = "..";
/// Group separator.
Expand Down Expand Up @@ -213,6 +215,11 @@ pub(crate) fn parse_lenses<'a>(
.parse_next(input)
}

/// A combinator which parses a keys operator.
pub(crate) fn parse_keys_operator<'a>(input: &mut &'a str) -> PResult<&'a str> {
literal(KEYS).parse_next(input)
}

/// A combinator which parses a flatten operator.
pub(crate) fn parse_flatten_operator<'a>(input: &mut &'a str) -> PResult<&'a str> {
literal(FLATTEN).parse_next(input)
Expand Down Expand Up @@ -243,6 +250,7 @@ mod tests {
use super::{
FLATTEN,
GROUP_SEP,
KEYS,
PIPE_IN,
PIPE_OUT,
TRUNCATE,
Expand All @@ -252,6 +260,7 @@ mod tests {
parse_group_separator,
parse_indexes,
parse_key,
parse_keys_operator,
parse_lens,
parse_lenses,
parse_multi_key,
Expand Down Expand Up @@ -347,6 +356,12 @@ mod tests {
assert!(parse_object_range(&mut "{}").is_err());
}

#[test]
fn check_parse_keys_operator() {
assert_eq!(parse_keys_operator(&mut "@"), Ok(KEYS));
assert!(parse_keys_operator(&mut "").is_err());
}

#[test]
fn check_parse_flatten_operator() {
assert_eq!(parse_flatten_operator(&mut ".."), Ok(FLATTEN));
Expand Down
2 changes: 2 additions & 0 deletions crates/jql-parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::{
parse_flatten_operator,
parse_group_separator,
parse_key,
parse_keys_operator,
parse_lenses,
parse_multi_key,
parse_object_index,
Expand Down Expand Up @@ -67,6 +68,7 @@ fn parse_fragment<'a>(input: &mut &'a str) -> PResult<Token<'a>> {
parse_pipe_in_operator.value(Token::PipeInOperator),
))
},
'@' => parse_keys_operator.value(Token::KeyOperator),
'.' => parse_flatten_operator.value(Token::FlattenOperator),
'<' => parse_pipe_out_operator.value(Token::PipeOutOperator),
',' => parse_group_separator.value(Token::GroupSeparator),
Expand Down
10 changes: 7 additions & 3 deletions crates/jql-parser/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl<'a> Lens<'a> {
}
}

impl<'a> fmt::Display for Lens<'a> {
impl fmt::Display for Lens<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", self.0.stringify(), match &self.1 {
Some(lens_value) => {
Expand All @@ -125,7 +125,7 @@ pub enum LensValue<'a> {
String(&'a str),
}

impl<'a> fmt::Display for LensValue<'a> {
impl fmt::Display for LensValue<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LensValue::Bool(boolean) => {
Expand All @@ -151,6 +151,8 @@ pub enum Token<'a> {
ArrayRangeSelector(Range),
/// Flatten operator.
FlattenOperator,
/// Key operator.
KeyOperator,
/// Group separator.
GroupSeparator,
/// Key selector.
Expand All @@ -177,6 +179,7 @@ impl<'a> Token<'a> {
Token::ArrayIndexSelector(_) => "Array Index Selector",
Token::ArrayRangeSelector(_) => "Array Range Selector",
Token::FlattenOperator => "Flatten Operator",
Token::KeyOperator => "Key Operator",
Token::GroupSeparator => "Group Separator",
Token::KeySelector(_) => "Key Selector",
Token::LensSelector(_) => "Lens Selector",
Expand All @@ -190,7 +193,7 @@ impl<'a> Token<'a> {
}
}

impl<'a> fmt::Display for Token<'a> {
impl fmt::Display for Token<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Token::ArrayIndexSelector(indexes) | Token::ObjectIndexSelector(indexes) => {
Expand Down Expand Up @@ -223,6 +226,7 @@ impl<'a> fmt::Display for Token<'a> {
write!(f, "{} {formatted_keys}", self.get_name())
}
Token::FlattenOperator
| Token::KeyOperator
| Token::GroupSeparator
| Token::PipeInOperator
| Token::PipeOutOperator
Expand Down
2 changes: 1 addition & 1 deletion crates/jql-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repository.workspace = true
version.workspace = true

[dependencies]
indexmap = { version = "2.5.0", features = ["rayon"] }
indexmap = { version = "2.6.0", features = ["rayon"] }
jql-parser = { path = "../jql-parser", version = "7.2.0" }
rayon = "1.10.0"
serde_json.workspace = true
Expand Down
31 changes: 31 additions & 0 deletions crates/jql-runner/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,29 @@ pub(crate) fn get_array_lenses(lenses: &[Lens], json: &mut Value) -> Result<Valu
Ok(json!(result))
}

/// Takes a reference of a JSON `Value`.
/// Converts the original array as indexes and returns a JSON `Value` or an error.
/// Note: the runner checks that the input is a JSON array.
pub(crate) fn get_array_as_indexes(json: &Value) -> Result<Value, JqlRunnerError> {
let result = json
.as_array()
.unwrap()
.par_iter()
.enumerate()
.try_fold_with(Vec::new(), |mut acc: Vec<Value>, (i, _)| {
acc.push(i.into());

Ok::<Vec<Value>, JqlRunnerError>(acc)
})
.try_reduce(Vec::new, |mut a, b| {
a.extend(b);

Ok(a)
})?;

Ok(json!(result))
}

#[cfg(test)]
mod tests {
use jql_parser::tokens::{
Expand All @@ -190,6 +213,7 @@ mod tests {
use serde_json::json;

use super::{
get_array_as_indexes,
get_array_index,
get_array_indexes,
get_array_lenses,
Expand Down Expand Up @@ -230,6 +254,13 @@ mod tests {
);
}

#[test]
fn check_get_array_as_indexes() {
let value = json!(["a", "b", "c"]);

assert_eq!(get_array_as_indexes(&value), Ok(json!([0, 1, 2])));
}

#[test]
fn check_get_array_range() {
let value = json!(["a", "b", "c", "d", "e"]);
Expand Down
Loading

0 comments on commit 43393c5

Please sign in to comment.