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
//! # `url_query_string` Procedural Macro Crate
//!
//! The `url_query_string` crate provides a procedural macro `#[derive(ToQueryString)]`
//! for automatically generating methods to serialize Rust structs into URL query strings.
//!
//! This crate leverages `serde_qs` for serialization, ensuring compatibility with
//! `serde` and its powerful features. By deriving `ToQueryString`, two methods are
//! added to your struct:
//!
//! - `to_query_string`: Converts the struct to a query string, ignoring errors and returning
//! an empty string in case of failure.
//! - `try_to_query_string`: Returns a `Result` containing either the query string or
//! a serialization error from `serde_qs`.
//!
//! ## Features
//!
//! - **Automatic Query String Generation**: Simplifies converting structs into URL-friendly query strings.
//! - **Compatible with `serde`**: Supports serialization conventions like `camelCase` or `snake_case`
//! through `serde` attributes.
//! - **Error Handling**: Offers `try_to_query_string` for cases where error handling is necessary.
//!
//! ## Usage
//!
//! ### Add the Crate
//!
//! Add the crate to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! url_query_string = "0.1"
//! serde = { version = "1.0", features = ["derive"] }
//! serde_qs = "0.7"
//! ```
//!
//! ### Example
//!
//! ```rust
//! use serde::Serialize;
//! use url_query_string::ToQueryString;
//!
//! #[derive(Serialize, ToQueryString)]
//! #[serde(rename_all = "camelCase")]
//! struct TestStruct {
//! pub page: Option<u32>,
//! pub page_size: Option<u32>,
//! pub id: Option<String>,
//! pub user_id: Option<String>,
//! }
//!
//! fn main() {
//! let instance = TestStruct {
//! page: Some(1),
//! page_size: Some(20),
//! id: Some("test_id".to_string()),
//! user_id: Some("user_123".to_string()),
//! };
//!
//! // Generate query string (ignores errors).
//! let query_string = instance.to_query_string();
//! println!("Query String: {}", query_string);
//!
//! // Generate query string with error handling.
//! match instance.try_to_query_string() {
//! Ok(qs) => println!("Query String (with Result): {}", qs),
//! Err(e) => eprintln!("Error: {}", e),
//! }
//! }
//! ```
//!
//! ### Output
//!
//! Running the example above will produce:
//!
//! ```text
//! Query String: page=1&pageSize=20&id=test_id&userId=user_123
//! Query String (with Result): page=1&pageSize=20&id=test_id&userId=user_123
//! ```
//!
//! ## Integration with `serde`
//!
//! The crate uses `serde` attributes to control the serialization behavior. For example, you can
//! use `#[serde(rename_all = "snake_case")]` to adjust the case of field names in the query string.
//!
//! ### Example with `snake_case`
//!
//! ```rust
//! use serde::Serialize;
//! use url_query_string::ToQueryString;
//!
//! #[derive(Serialize, ToQueryString)]
//! #[serde(rename_all = "snake_case")]
//! struct AnotherStruct {
//! pub user_name: Option<String>,
//! pub access_token: Option<String>,
//! }
//! ```
//!
//! This will generate query strings like:
//!
//! ```text
//! user_name=test_user&access_token=abcd1234
//! ```
//!
//! ## Generated Methods
//!
//! When deriving `ToQueryString`, the following methods are added to your struct:
//!
//! - `pub fn to_query_string(&self) -> String`: Converts the struct into a query string. Returns
//! an empty string if serialization fails.
//!
//! - `pub fn try_to_query_string(&self) -> Result<String, serde_qs::Error>`: Converts the struct into
//! a query string. Returns a `Result` with either the query string or an error.
//!
//! ## Contribution
//!
//! Contributions are welcome! If you encounter any bugs or have feature requests, please
//! open an issue or submit a pull request on [GitHub](https://github.com/your-repo/url_query_string).
extern crate proc_macro;
use TokenStream;
use quote;
use ;
/// Procedural macro to derive query string serialization methods for structs.
///
/// This macro generates two methods for the struct:
///
/// - `to_query_string`: Converts the struct to a query string as a `String`.
/// It ignores errors, returning an empty string (`""`) if serialization fails.
/// - `try_to_query_string`: Converts the struct to a query string as a `Result<String, serde_qs::Error>`.
/// This method allows handling errors during serialization.
///
/// ## Usage
///
/// The struct must implement the `serde::Serialize` trait, as the macro relies on
/// `serde_qs` for query string serialization. You can use `serde` attributes like
/// `#[serde(rename_all = "camelCase")]` to customize the query string format.
///
/// ### Example
///
/// ```rust
/// use serde::Serialize;
/// use url_query_string::ToQueryString;
///
/// #[derive(Serialize, ToQueryString)]
/// #[serde(rename_all = "camelCase")]
/// struct ExampleStruct {
/// pub user_id: Option<String>,
/// pub page: Option<u32>,
/// }
///
/// let instance = ExampleStruct {
/// user_id: Some("user_123".to_string()),
/// page: Some(1),
/// };
///
/// // Generate query string
/// assert_eq!(instance.to_query_string(), "userId=user_123&page=1");
/// ```