serde_query/
lib.rs

1//! A query language for Serde data model.
2//!
3//! This crate provides [`serde_query::Deserialize`] and [`serde_query::DeserializeQuery`] derive
4//! macros that generate [`serde::Deserialize`] implementations with queries.
5//!
6//! # Example
7//!
8//! ```rust
9//! # use std::error::Error;
10//! # fn main() -> Result<(), Box<dyn Error + 'static>> {
11//! use serde_query::Deserialize;
12//!
13//! #[derive(Deserialize)]
14//! struct Data {
15//!     #[query(".commits.[].author")]
16//!     authors: Vec<String>,
17//!     #[query(".count")]
18//!     count: usize,
19//! }
20//!
21//! let document = serde_json::json!({
22//!     "commits": [
23//!         {
24//!             "author": "Kou",
25//!             "hash": 0x0202,
26//!         },
27//!         {
28//!             "author": "Kasumi",
29//!             "hash": 0x1013,
30//!         },
31//!         {
32//!             "author": "Masaru",
33//!             "hash": 0x0809,
34//!         },
35//!     ],
36//!     "count": 3,
37//! }).to_string();
38//!
39//! let data: Data = serde_json::from_str(&document)?;
40//!
41//! assert_eq!(data.authors, vec!["Kou", "Kasumi", "Masaru"]);
42//! assert_eq!(data.count, 3);
43//! # Ok(())
44//! # }
45//! ```
46//!
47//! # Derive macros
48//!
49//! This crate provides the following derive macros for declaring queries:
50//! * [`serde_query::Deserialize`] generates an implementation of [`serde::Deserialize`] for the struct.
51//!   We recommend using a full-path form (`serde_query::Deserialize`) when deriving to disambiguate
52//!   between serde and this crate.
53//! * [`serde_query::DeserializeQuery`] generates [`serde::Deserialize`] for [`Query<T>`] wrapper.
54//!   This derive macro is useful if you want two `Deserialize` implementation.
55//!   For example, you may want `DeserializeQuery` for querying an API and `Deserialize` for loading from file.
56//!
57//! # Using the `#[query("...")]` annotation
58//!
59//! serde-query let you write a jq-like query inside the `#[query("...")]` annotation.
60//! Note that every field must have a query annotation.
61//!
62//! The supported syntaxes are as follows:
63//!
64//! * **`.field` syntax:** You can use the `.field` syntax to extract a field from a struct.
65//!   For example, `.name` extracts the `name` field. If the field name contains special characters, you can use the `.["field"]` syntax to quote the field name.
66//!   For example, `.["first-name"]` extracts the `first-name` field.
67//!   When quoting a field name, try using a raw string literal (i.e., `#[query(r#"..."#)]`).
68//! * **`.[]` syntax:** You can use the `.[]` syntax to run the rest of the query for each element in an array and collect the results.
69//!   For example, `.friends.[].name` extracts the `name` field from each element in the `friends` array.
70//! * **`.[n]` syntax:** You can use the `.[n]` syntax to extract the nth element from an array.
71//!   For example, `.friends.[0]` extracts the first element of the `friends` array.
72//!
73//! [`serde::Deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html
74//! [`serde_query::Deserialize`]: derive.Deserialize.html
75//! [`serde_query::DeserializeQuery`]: trait.DeserializeQuery.html
76//! [`Query<T>`]: trait.DeserializeQuery.html#associatedtype.Query
77
78/// Derive macro that generates [`serde::Deserialize`] directly.
79///
80/// Please refer to the [module-level documentation] for the usage.
81///
82/// [`serde::Deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html
83/// [module-level documentation]: index.html
84pub use serde_query_derive::Deserialize;
85
86/// Derive macro for [`DeserializeQuery`] trait.
87///
88/// Please refer to the [module-level documentation] for the usage.
89///
90/// # Example
91///
92/// ```rust
93/// # use std::error::Error;
94/// # fn main() -> Result<(), Box<dyn Error + 'static>> {
95/// use serde_query::{DeserializeQuery, Query};
96///
97/// #[derive(DeserializeQuery)]
98/// struct Data {
99///     #[query(".commits.[].author")]
100///     authors: Vec<String>,
101///     #[query(".count")]
102///     count: usize,
103/// }
104///
105/// let document = serde_json::json!({
106///     "commits": [
107///         {
108///             "author": "Kou",
109///             "hash": 0x0202,
110///         },
111///         {
112///             "author": "Kasumi",
113///             "hash": 0x1013,
114///         },
115///         {
116///             "author": "Masaru",
117///             "hash": 0x0809,
118///         },
119///     ],
120///     "count": 3,
121/// }).to_string();
122///
123/// // You can use `Query<T>` as a `Deserialize` type for any `Deserializer`
124/// // and convert the result to the desired type using `From`/`Into`.
125/// let data: Data = serde_json::from_str::<Query<Data>>(&document)?.into();
126///
127/// assert_eq!(data.authors, vec!["Kou", "Kasumi", "Masaru"]);
128/// assert_eq!(data.count, 3);
129/// # Ok(())
130/// # }
131/// ```
132///
133/// [`DeserializeQuery`]: trait.DeserializeQuery.html
134/// [module-level documentation]: index.html
135pub use serde_query_derive::DeserializeQuery;
136
137use core::ops::{Deref, DerefMut};
138use serde::de::Deserialize;
139
140/// Convenient type alias for the query type.
141///
142/// Please refer to the [`DeserializeQuery`] trait for details.
143///
144/// [`DeserializeQuery`]: trait.DeserializeQuery.html
145pub type Query<'de, T> = <T as DeserializeQuery<'de>>::Query;
146
147/// A **data structure** that can be deserialized with a query.
148///
149/// The [`Query`] type is a `#[repr(transparent)]` wrapper automatically generated by
150/// [the proc macro]. You can deserialize `Query<YourType>` first and then call `.into()`
151/// to get `YourType`.
152///
153/// [`Query`]: trait.DeserializeQuery.html#associatedtype.Query
154/// [the proc macro]: derive.DeserializeQuery.html
155pub trait DeserializeQuery<'de>
156where
157    Self: From<<Self as DeserializeQuery<'de>>::Query>,
158    Self::Query: Deserialize<'de> + Deref<Target = Self> + DerefMut,
159{
160    /// The query type.
161    type Query;
162}
163
164// This module can only be used inside the generated code.
165#[doc(hidden)]
166pub mod __priv {
167    pub use serde;
168
169    extern crate alloc;
170
171    #[derive(Debug)]
172    pub struct Error {
173        field: &'static str,
174        prefix: &'static str,
175        message: alloc::borrow::Cow<'static, str>,
176    }
177
178    impl core::fmt::Display for Error {
179        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
180            write!(
181                f,
182                "Query for field '{}' failed at '{}': {}",
183                self.field, self.prefix, self.message
184            )
185        }
186    }
187
188    impl Error {
189        pub fn owned(field: &'static str, prefix: &'static str, message: String) -> Self {
190            Error {
191                field,
192                prefix,
193                message: alloc::borrow::Cow::Owned(message),
194            }
195        }
196
197        pub fn borrowed(field: &'static str, prefix: &'static str, message: &'static str) -> Self {
198            Error {
199                field,
200                prefix,
201                message: alloc::borrow::Cow::Borrowed(message),
202            }
203        }
204    }
205
206    #[derive(Debug)]
207    pub struct Errors<'a> {
208        errors: &'a [Option<Error>],
209    }
210
211    impl<'a> core::fmt::Display for Errors<'a> {
212        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
213            match self.error_count() {
214                0 => Ok(()),
215                1 => {
216                    let error = self.errors().next().unwrap();
217                    error.fmt(f)
218                }
219                _ => {
220                    write!(f, "Queries failed for fields: ")?;
221                    let mut following = false;
222                    for error in self.errors() {
223                        if following {
224                            f.write_str(", ")?;
225                        }
226                        write!(f, "'{}'", error.field)?;
227                        following = true;
228                    }
229                    f.write_str("\n")?;
230
231                    let mut index = 1;
232                    for error in self.errors() {
233                        writeln!(f, "  {}. {}", index, error)?;
234                        index += 1;
235                    }
236
237                    Ok(())
238                }
239            }
240        }
241    }
242
243    impl<'a> Errors<'a> {
244        pub fn new(errors: &'a [Option<Error>]) -> Self {
245            Self { errors }
246        }
247
248        fn error_count(&self) -> usize {
249            self.errors
250                .iter()
251                .map(|opt| if opt.is_some() { 1 } else { 0 })
252                .sum()
253        }
254
255        fn errors(&self) -> impl Iterator<Item = &Error> {
256            self.errors.iter().flatten()
257        }
258    }
259
260    pub trait Container {
261        type Element;
262
263        fn empty() -> Self;
264
265        fn reserve(&mut self, additional: usize);
266
267        fn extend_one(&mut self, element: Self::Element);
268    }
269
270    impl<T> Container for alloc::vec::Vec<T> {
271        type Element = T;
272
273        fn empty() -> Self {
274            Self::new()
275        }
276
277        fn reserve(&mut self, additional: usize) {
278            self.reserve(additional);
279        }
280
281        fn extend_one(&mut self, element: Self::Element) {
282            self.push(element);
283        }
284    }
285
286    impl<T> Container for alloc::collections::VecDeque<T> {
287        type Element = T;
288
289        fn empty() -> Self {
290            Self::new()
291        }
292
293        fn reserve(&mut self, additional: usize) {
294            self.reserve(additional);
295        }
296
297        fn extend_one(&mut self, element: Self::Element) {
298            self.push_back(element);
299        }
300    }
301
302    impl<T: core::cmp::Ord> Container for alloc::collections::BTreeSet<T> {
303        type Element = T;
304
305        fn empty() -> Self {
306            Self::new()
307        }
308
309        fn reserve(&mut self, _additional: usize) {
310            // do nothing
311        }
312
313        fn extend_one(&mut self, element: Self::Element) {
314            self.insert(element);
315        }
316    }
317
318    impl<T: core::cmp::Eq + core::hash::Hash> Container for std::collections::HashSet<T> {
319        type Element = T;
320
321        fn empty() -> Self {
322            Self::new()
323        }
324
325        fn reserve(&mut self, additional: usize) {
326            self.reserve(additional);
327        }
328
329        fn extend_one(&mut self, element: Self::Element) {
330            self.insert(element);
331        }
332    }
333}