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}