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

/// Derive macro that generates [`serde::Deserialize`] directly.
///
/// Please refer to the [module-level documentation] for the usage.
///
/// [`serde::Deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html
/// [module-level documentation]: index.html
pub use serde_query_derive::Deserialize;

/// Derive macro for [`DeserializeQuery`] trait.
///
/// Please refer to the [module-level documentation] for the usage.
///
/// # Example
///
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error + 'static>> {
/// use serde_query::{DeserializeQuery, Query};
///
/// #[derive(DeserializeQuery)]
/// struct Data {
///     #[query(".commits.[].author")]
///     authors: Vec<String>,
///     #[query(".count")]
///     count: usize,
/// }
///
/// let document = serde_json::json!({
///     "commits": [
///         {
///             "author": "Kou",
///             "hash": 0x0202,
///         },
///         {
///             "author": "Kasumi",
///             "hash": 0x1013,
///         },
///         {
///             "author": "Masaru",
///             "hash": 0x0809,
///         },
///     ],
///     "count": 3,
/// }).to_string();
///
/// // You can use `Query<T>` as a `Deserialize` type for any `Deserializer`
/// // and convert the result to the desired type using `From`/`Into`.
/// let data: Data = serde_json::from_str::<Query<Data>>(&document)?.into();
///
/// assert_eq!(data.authors, vec!["Kou", "Kasumi", "Masaru"]);
/// assert_eq!(data.count, 3);
/// # Ok(())
/// # }
/// ```
///
/// [`DeserializeQuery`]: trait.DeserializeQuery.html
/// [module-level documentation]: index.html
pub use serde_query_derive::DeserializeQuery;

use core::ops::{Deref, DerefMut};
use serde::de::Deserialize;

/// Convenient type alias for the query type.
///
/// Please refer to the [`DeserializeQuery`] trait for details.
///
/// [`DeserializeQuery`]: trait.DeserializeQuery.html
pub type Query<'de, T> = <T as DeserializeQuery<'de>>::Query;

/// A **data structure** that can be deserialized with a query.
///
/// The [`Query`] type is a `#[repr(transparent)]` wrapper automatically generated by
/// [the proc macro]. You can deserialize `Query<YourType>` first and then call `.into()`
/// to get `YourType`.
///
/// [`Query`]: trait.DeserializeQuery.html#associatedtype.Query
/// [the proc macro]: derive.DeserializeQuery.html
pub trait DeserializeQuery<'de>
where
    Self: From<<Self as DeserializeQuery<'de>>::Query>,
    Self::Query: Deserialize<'de> + Deref<Target = Self> + DerefMut,
{
    /// The query type.
    type Query;
}

// This module can only be used inside the generated code.
#[doc(hidden)]
pub mod __priv {
    pub use serde;

    extern crate alloc;

    #[derive(Debug)]
    pub struct Error {
        field: &'static str,
        prefix: &'static str,
        message: alloc::borrow::Cow<'static, str>,
    }

    impl core::fmt::Display for Error {
        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
            write!(
                f,
                "Query for field '{}' failed at '{}': {}",
                self.field, self.prefix, self.message
            )
        }
    }

    impl Error {
        pub fn owned(field: &'static str, prefix: &'static str, message: String) -> Self {
            Error {
                field,
                prefix,
                message: alloc::borrow::Cow::Owned(message),
            }
        }

        pub fn borrowed(field: &'static str, prefix: &'static str, message: &'static str) -> Self {
            Error {
                field,
                prefix,
                message: alloc::borrow::Cow::Borrowed(message),
            }
        }
    }

    #[derive(Debug)]
    pub struct Errors<'a> {
        errors: &'a [Option<Error>],
    }

    impl<'a> core::fmt::Display for Errors<'a> {
        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
            match self.error_count() {
                0 => Ok(()),
                1 => {
                    let error = self.errors().next().unwrap();
                    error.fmt(f)
                }
                _ => {
                    write!(f, "Queries failed for fields: ")?;
                    let mut following = false;
                    for error in self.errors() {
                        if following {
                            f.write_str(", ")?;
                        }
                        write!(f, "'{}'", error.field)?;
                        following = true;
                    }
                    f.write_str("\n")?;

                    let mut index = 1;
                    for error in self.errors() {
                        writeln!(f, "  {}. {}", index, error)?;
                        index += 1;
                    }

                    Ok(())
                }
            }
        }
    }

    impl<'a> Errors<'a> {
        pub fn new(errors: &'a [Option<Error>]) -> Self {
            Self { errors }
        }

        fn error_count(&self) -> usize {
            self.errors
                .iter()
                .map(|opt| if opt.is_some() { 1 } else { 0 })
                .sum()
        }

        fn errors(&self) -> impl Iterator<Item = &Error> {
            self.errors.iter().flatten()
        }
    }

    pub trait Container {
        type Element;

        fn empty() -> Self;

        fn reserve(&mut self, additional: usize);

        fn extend_one(&mut self, element: Self::Element);
    }

    impl<T> Container for alloc::vec::Vec<T> {
        type Element = T;

        fn empty() -> Self {
            Self::new()
        }

        fn reserve(&mut self, additional: usize) {
            self.reserve(additional);
        }

        fn extend_one(&mut self, element: Self::Element) {
            self.push(element);
        }
    }

    impl<T> Container for alloc::collections::VecDeque<T> {
        type Element = T;

        fn empty() -> Self {
            Self::new()
        }

        fn reserve(&mut self, additional: usize) {
            self.reserve(additional);
        }

        fn extend_one(&mut self, element: Self::Element) {
            self.push_back(element);
        }
    }

    impl<T: core::cmp::Ord> Container for alloc::collections::BTreeSet<T> {
        type Element = T;

        fn empty() -> Self {
            Self::new()
        }

        fn reserve(&mut self, _additional: usize) {
            // do nothing
        }

        fn extend_one(&mut self, element: Self::Element) {
            self.insert(element);
        }
    }

    impl<T: core::cmp::Eq + core::hash::Hash> Container for std::collections::HashSet<T> {
        type Element = T;

        fn empty() -> Self {
            Self::new()
        }

        fn reserve(&mut self, additional: usize) {
            self.reserve(additional);
        }

        fn extend_one(&mut self, element: Self::Element) {
            self.insert(element);
        }
    }
}