use jql_parser::errors::JqlParserError;
use serde_json::Value;
use thiserror::Error;
static SLICE_SEP: &str = " ... ";
static SLICE_LEN: usize = 7;
static SEP: &str = ", ";
fn join(values: &[String]) -> String {
values.join(SEP)
}
fn shorten(json: &Value) -> String {
let full_json_string = json.to_string();
if full_json_string.len() < SLICE_LEN * 2 + SLICE_SEP.len() {
return full_json_string;
}
let start_slice = &full_json_string[..SLICE_LEN];
let end_slice = &full_json_string[full_json_string.len() - SLICE_LEN..];
[start_slice, end_slice].join(SLICE_SEP)
}
fn get_json_type(json: &Value) -> &str {
match json {
Value::Array(_) => "array",
Value::Bool(_) => "boolean",
Value::Null => "null",
Value::Number(_) => "number",
Value::Object(_) => "object",
Value::String(_) => "string",
}
}
#[derive(Debug, Error, PartialEq)]
pub enum JqlRunnerError {
#[error("Query is empty")]
EmptyQueryError,
#[error("Value {0} is neither an array nor an object and can't be flattened")]
FlattenError(Value),
#[error("Index {index} in parent {parent} is out of bounds")]
IndexOutOfBoundsError {
index: usize,
parent: Value,
},
#[error("Value {0} is not a JSON array ({})", get_json_type(.0))]
InvalidArrayError(Value),
#[error("Value {0} is not a JSON object ({})", get_json_type(.0))]
InvalidObjectError(Value),
#[error(r#"Key "{key}" doesn't exist in parent {}"#, shorten(parent))]
KeyNotFoundError {
key: String,
parent: Value,
},
#[error("Keys {} don't exist in parent {}", join(keys), shorten(parent))]
MultiKeyNotFoundError {
keys: Vec<String>,
parent: Value,
},
#[error(transparent)]
ParsingError(#[from] JqlParserError),
#[error("Pipe in operator used on {0} which is not an array")]
PipeInError(Value),
#[error("Pipe out operator used without a preceding pipe in operator")]
PipeOutError,
#[error("Range [{start}:{end}] in parent {parent} is out of bounds")]
RangeOutOfBoundsError {
start: usize,
end: usize,
parent: Value,
},
#[error("Unknown error")]
UnknownError,
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::{
get_json_type,
join,
shorten,
};
#[test]
fn check_get_json_type() {
assert_eq!(get_json_type(&json!([])), "array");
assert_eq!(get_json_type(&json!(true)), "boolean");
assert_eq!(get_json_type(&json!(null)), "null");
assert_eq!(get_json_type(&json!(1)), "number");
assert_eq!(get_json_type(&json!({})), "object");
assert_eq!(get_json_type(&json!("a")), "string");
}
#[test]
fn check_join() {
assert_eq!(
join(&["a".to_string(), "b".to_string(), "c".to_string()]),
"a, b, c".to_string()
);
}
#[test]
fn check_shorten() {
assert_eq!(shorten(&json!("thismakesnosense")), r#""thismakesnosense""#);
assert_eq!(
shorten(&json!({ "a": { "b": { "c": [1, 2 ,3, 4, 5, 6, 7, 8, 9] } } })),
r#"{"a":{" ... 8,9]}}}"#.to_string()
);
}
}