access_json/query.rs
1use crate::query_executor::{QueryExecErr, QueryExecutor};
2use crate::query_parser::{parse_query, QueryParseErr};
3use crate::AnySerializable;
4use serde::Serialize;
5
6#[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
7pub enum QueryElement {
8 Field(String),
9 ArrayItem(usize),
10}
11
12impl QueryElement {
13 pub fn field(field: &str) -> Self {
14 Self::Field(field.into())
15 }
16 pub fn array_item(index: usize) -> Self {
17 Self::ArrayItem(index)
18 }
19}
20
21impl std::fmt::Display for QueryElement {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 QueryElement::Field(name) => write!(f, ".{}", name),
25 QueryElement::ArrayItem(index) => write!(f, "[{}]", index),
26 }
27 }
28}
29
30/// This is the main interface to this library.
31/// Create a new JSONQuery by calling parse.
32#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
33pub struct JSONQuery {
34 /// A list of access-elements, field names or array indices.
35 pub elements: Vec<QueryElement>,
36}
37
38/// This is a way to visualize a JSONQuery object as a parse-able string.
39impl std::fmt::Display for JSONQuery {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 for elem in self.elements.iter() {
42 write!(f, "{}", elem)?
43 }
44 Ok(())
45 }
46}
47
48impl JSONQuery {
49 /// Construct a new JSONQuery object from discrete elements.
50 pub(crate) fn new(elements: Vec<QueryElement>) -> Self {
51 Self { elements }
52 }
53
54 /// Construct a new JSONQuery object from an example string.
55 ///
56 /// ```
57 /// use access_json::JSONQuery;
58 /// use access_json::query::QueryElement; // Only needed to validate our parsing.
59 ///
60 /// assert_eq!(
61 /// JSONQuery::parse(".field.array[8]").unwrap().elements,
62 /// vec![QueryElement::field("field"),
63 /// QueryElement::field("array"),
64 /// QueryElement::array_item(8)]);
65 /// ```
66 pub fn parse(input: &str) -> Result<Self, QueryParseErr> {
67 Ok(Self::new(parse_query(input)?))
68 }
69
70 #[cfg(test)]
71 pub fn single(q: QueryElement) -> Self {
72 Self::new(vec![q])
73 }
74
75 /// Execute a JSONQuery object against any serde-serializable object.
76 ///
77 /// ```
78 /// use access_json::JSONQuery;
79 /// use std::collections::HashMap;
80 /// use serde_json;
81 ///
82 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
83 /// let mut data: HashMap<&str, u32> = HashMap::default();
84 /// data.insert("cat", 9);
85 ///
86 /// let query = JSONQuery::parse(".cat")?;
87 /// let output = query.execute(&data)?;
88 /// let expected = serde_json::to_value(&9)?;
89 ///
90 /// assert_eq!(Some(expected), output);
91 /// # Ok(())
92 /// # }
93 /// ```
94 pub fn execute(
95 &self,
96 target: &dyn AnySerializable,
97 ) -> Result<Option<serde_json::Value>, QueryExecErr> {
98 let mut runner = QueryExecutor::new(self)?;
99 target.serialize(&mut runner)?;
100 Ok(runner.get_result())
101 }
102}