ruled_router/parser/
query.rs

1//! 查询参数解析器
2//!
3//! 提供查询字符串的解析和格式化功能
4
5use crate::error::{ParseError, ParseResult};
6use crate::utils::{format_query_string, parse_query_string};
7use std::collections::HashMap;
8
9/// 查询参数解析器
10///
11/// 负责解析查询字符串并提供类型安全的参数访问
12#[derive(Debug, Clone)]
13pub struct QueryParser {
14  /// 原始查询字符串
15  raw_query: String,
16  /// 解析后的参数映射
17  params: HashMap<String, Vec<String>>,
18}
19
20impl QueryParser {
21  /// 创建新的查询参数解析器
22  ///
23  /// # 参数
24  ///
25  /// * `query` - 查询字符串,不包含前导的 '?'
26  ///
27  /// # 返回值
28  ///
29  /// 解析器实例,如果解析失败则返回错误
30  ///
31  /// # 示例
32  ///
33  /// ```rust
34  /// use ruled_router::parser::QueryParser;
35  ///
36  /// let parser = QueryParser::new("q=rust&page=2&tags=web&tags=backend").unwrap();
37  /// ```
38  pub fn new(query: &str) -> ParseResult<Self> {
39    let params = parse_query_string(query)?;
40    Ok(Self {
41      raw_query: query.to_string(),
42      params,
43    })
44  }
45
46  /// 从参数映射创建查询解析器
47  ///
48  /// # 参数
49  ///
50  /// * `params` - 参数映射
51  ///
52  /// # 返回值
53  ///
54  /// 解析器实例
55  pub fn from_params(params: HashMap<String, Vec<String>>) -> Self {
56    let raw_query = format_query_string(&params);
57    Self { raw_query, params }
58  }
59
60  /// 获取单个参数值
61  ///
62  /// # 参数
63  ///
64  /// * `key` - 参数名
65  ///
66  /// # 返回值
67  ///
68  /// 参数的第一个值,如果参数不存在则返回 None
69  ///
70  /// # 示例
71  ///
72  /// ```rust
73  /// use ruled_router::parser::QueryParser;
74  ///
75  /// let parser = QueryParser::new("q=rust&page=2").unwrap();
76  /// assert_eq!(parser.get("q"), Some("rust"));
77  /// assert_eq!(parser.get("page"), Some("2"));
78  /// assert_eq!(parser.get("missing"), None);
79  /// ```
80  pub fn get(&self, key: &str) -> Option<&str> {
81    self.params.get(key)?.first().map(|s| s.as_str())
82  }
83
84  /// 获取多个参数值
85  ///
86  /// # 参数
87  ///
88  /// * `key` - 参数名
89  ///
90  /// # 返回值
91  ///
92  /// 参数的所有值,如果参数不存在则返回空切片
93  ///
94  /// # 示例
95  ///
96  /// ```rust
97  /// use ruled_router::parser::QueryParser;
98  ///
99  /// let parser = QueryParser::new("tags=web&tags=backend&tags=rust").unwrap();
100  /// let tags: Vec<&str> = parser.get_all("tags").iter().map(|s| s.as_str()).collect();
101  /// assert_eq!(tags, vec!["web", "backend", "rust"]);
102  /// ```
103  pub fn get_all(&self, key: &str) -> &[String] {
104    self.params.get(key).map(|v| v.as_slice()).unwrap_or(&[])
105  }
106
107  /// 检查参数是否存在
108  ///
109  /// # 参数
110  ///
111  /// * `key` - 参数名
112  ///
113  /// # 返回值
114  ///
115  /// 如果参数存在则返回 true,否则返回 false
116  pub fn contains(&self, key: &str) -> bool {
117    self.params.contains_key(key)
118  }
119
120  /// 获取参数的类型安全值
121  ///
122  /// # 参数
123  ///
124  /// * `key` - 参数名
125  ///
126  /// # 返回值
127  ///
128  /// 解析后的值,如果参数不存在或解析失败则返回错误
129  ///
130  /// # 示例
131  ///
132  /// ```rust
133  /// use ruled_router::parser::QueryParser;
134  ///
135  /// let parser = QueryParser::new("page=2&limit=10").unwrap();
136  /// let page: u32 = parser.get_parsed("page").unwrap();
137  /// let limit: u32 = parser.get_parsed("limit").unwrap();
138  /// assert_eq!(page, 2);
139  /// assert_eq!(limit, 10);
140  /// ```
141  pub fn get_parsed<T>(&self, key: &str) -> ParseResult<T>
142  where
143    T: crate::traits::FromParam,
144  {
145    let value = self.get(key).ok_or_else(|| ParseError::missing_parameter(key.to_string()))?;
146    T::from_param(value)
147  }
148
149  /// 获取可选的类型安全值
150  ///
151  /// # 参数
152  ///
153  /// * `key` - 参数名
154  ///
155  /// # 返回值
156  ///
157  /// 解析后的可选值,如果参数不存在则返回 None,如果解析失败则返回错误
158  ///
159  /// # 示例
160  ///
161  /// ```rust
162  /// use ruled_router::parser::QueryParser;
163  ///
164  /// let parser = QueryParser::new("page=2").unwrap();
165  /// let page: Option<u32> = parser.get_optional("page").unwrap();
166  /// let limit: Option<u32> = parser.get_optional("limit").unwrap();
167  /// assert_eq!(page, Some(2));
168  /// assert_eq!(limit, None);
169  /// ```
170  pub fn get_optional<T>(&self, key: &str) -> ParseResult<Option<T>>
171  where
172    T: crate::traits::FromParam,
173  {
174    match self.get(key) {
175      Some(value) => T::from_param(value).map(Some),
176      None => Ok(None),
177    }
178  }
179
180  /// 获取带默认值的类型安全值
181  ///
182  /// # 参数
183  ///
184  /// * `key` - 参数名
185  /// * `default` - 默认值
186  ///
187  /// # 返回值
188  ///
189  /// 解析后的值,如果参数不存在则返回默认值,如果解析失败则返回错误
190  ///
191  /// # 示例
192  ///
193  /// ```rust
194  /// use ruled_router::parser::QueryParser;
195  ///
196  /// let parser = QueryParser::new("page=2").unwrap();
197  /// let page: u32 = parser.get_with_default("page", 1).unwrap();
198  /// let limit: u32 = parser.get_with_default("limit", 10).unwrap();
199  /// assert_eq!(page, 2);
200  /// assert_eq!(limit, 10);
201  /// ```
202  pub fn get_with_default<T>(&self, key: &str, default: T) -> ParseResult<T>
203  where
204    T: crate::traits::FromParam,
205  {
206    match self.get(key) {
207      Some(value) => T::from_param(value),
208      None => Ok(default),
209    }
210  }
211
212  /// 获取多值参数的类型安全值
213  ///
214  /// # 参数
215  ///
216  /// * `key` - 参数名
217  ///
218  /// # 返回值
219  ///
220  /// 解析后的值向量,如果任何值解析失败则返回错误
221  ///
222  /// # 示例
223  ///
224  /// ```rust
225  /// use ruled_router::parser::QueryParser;
226  ///
227  /// let parser = QueryParser::new("ids=1&ids=2&ids=3").unwrap();
228  /// let ids: Vec<u32> = parser.get_all_parsed("ids").unwrap();
229  /// assert_eq!(ids, vec![1, 2, 3]);
230  /// ```
231  pub fn get_all_parsed<T>(&self, key: &str) -> ParseResult<Vec<T>>
232  where
233    T: crate::traits::FromParam,
234  {
235    let values = self.get_all(key);
236    values.iter().map(|s| T::from_param(s)).collect::<ParseResult<Vec<_>>>()
237  }
238
239  /// 设置参数值
240  ///
241  /// # 参数
242  ///
243  /// * `key` - 参数名
244  /// * `value` - 参数值
245  pub fn set<T>(&mut self, key: &str, value: T)
246  where
247    T: crate::traits::ToParam,
248  {
249    let value_str = value.to_param();
250    self.params.insert(key.to_string(), vec![value_str]);
251    self.update_raw_query();
252  }
253
254  /// 添加参数值(支持多值)
255  ///
256  /// # 参数
257  ///
258  /// * `key` - 参数名
259  /// * `value` - 参数值
260  pub fn add<T>(&mut self, key: &str, value: T)
261  where
262    T: crate::traits::ToParam,
263  {
264    let value_str = value.to_param();
265    self.params.entry(key.to_string()).or_default().push(value_str);
266    self.update_raw_query();
267  }
268
269  /// 移除参数
270  ///
271  /// # 参数
272  ///
273  /// * `key` - 参数名
274  ///
275  /// # 返回值
276  ///
277  /// 被移除的参数值,如果参数不存在则返回 None
278  pub fn remove(&mut self, key: &str) -> Option<Vec<String>> {
279    let result = self.params.remove(key);
280    self.update_raw_query();
281    result
282  }
283
284  /// 清空所有参数
285  pub fn clear(&mut self) {
286    self.params.clear();
287    self.raw_query.clear();
288  }
289
290  /// 获取所有参数名
291  ///
292  /// # 返回值
293  ///
294  /// 参数名的向量
295  pub fn keys(&self) -> Vec<&str> {
296    self.params.keys().map(|s| s.as_str()).collect()
297  }
298
299  /// 检查是否为空
300  ///
301  /// # 返回值
302  ///
303  /// 如果没有任何参数则返回 true
304  pub fn is_empty(&self) -> bool {
305    self.params.is_empty()
306  }
307
308  /// 获取参数数量
309  ///
310  /// # 返回值
311  ///
312  /// 参数的数量(不是值的数量)
313  pub fn len(&self) -> usize {
314    self.params.len()
315  }
316
317  /// 格式化为查询字符串
318  ///
319  /// # 返回值
320  ///
321  /// 格式化后的查询字符串,不包含前导的 '?'
322  ///
323  /// # 示例
324  ///
325  /// ```rust
326  /// use ruled_router::parser::QueryParser;
327  ///
328  /// let parser = QueryParser::new("q=rust&page=2").unwrap();
329  /// let formatted = parser.format();
330  /// // 注意:HashMap 的迭代顺序不确定
331  /// assert!(formatted.contains("q=rust"));
332  /// assert!(formatted.contains("page=2"));
333  /// ```
334  pub fn format(&self) -> String {
335    self.raw_query.clone()
336  }
337
338  /// 获取原始查询字符串
339  pub fn raw(&self) -> &str {
340    &self.raw_query
341  }
342
343  /// 获取参数映射的引用
344  pub fn params(&self) -> &HashMap<String, Vec<String>> {
345    &self.params
346  }
347
348  /// 更新原始查询字符串
349  fn update_raw_query(&mut self) {
350    self.raw_query = format_query_string(&self.params);
351  }
352}
353
354/// 查询参数构建器
355///
356/// 提供链式调用的方式构建查询参数
357#[derive(Debug, Default)]
358pub struct QueryBuilder {
359  params: HashMap<String, Vec<String>>,
360}
361
362impl QueryBuilder {
363  /// 创建新的查询构建器
364  pub fn new() -> Self {
365    Self::default()
366  }
367
368  /// 设置参数值
369  pub fn set<T>(mut self, key: &str, value: T) -> Self
370  where
371    T: crate::traits::ToParam,
372  {
373    let value_str = value.to_param();
374    self.params.insert(key.to_string(), vec![value_str]);
375    self
376  }
377
378  /// 添加参数值(支持多值)
379  pub fn add<T>(mut self, key: &str, value: T) -> Self
380  where
381    T: crate::traits::ToParam,
382  {
383    let value_str = value.to_param();
384    self.params.entry(key.to_string()).or_default().push(value_str);
385    self
386  }
387
388  /// 构建查询解析器
389  pub fn build(self) -> QueryParser {
390    QueryParser::from_params(self.params)
391  }
392
393  /// 构建查询字符串
394  pub fn build_string(self) -> String {
395    format_query_string(&self.params)
396  }
397}
398
399#[cfg(test)]
400mod tests {
401  use super::*;
402
403  #[test]
404  fn test_parse_simple_query() {
405    let parser = QueryParser::new("q=rust&page=2").unwrap();
406
407    assert_eq!(parser.get("q"), Some("rust"));
408    assert_eq!(parser.get("page"), Some("2"));
409    assert_eq!(parser.get("missing"), None);
410  }
411
412  #[test]
413  fn test_parse_multi_value_query() {
414    let parser = QueryParser::new("tags=web&tags=backend&tags=rust").unwrap();
415
416    let tags = parser.get_all("tags");
417    assert_eq!(tags, &["web", "backend", "rust"]);
418
419    assert_eq!(parser.get("tags"), Some("web")); // 第一个值
420  }
421
422  #[test]
423  fn test_empty_query() {
424    let parser = QueryParser::new("").unwrap();
425
426    assert!(parser.is_empty());
427    assert_eq!(parser.len(), 0);
428    assert_eq!(parser.keys(), Vec::<&str>::new());
429  }
430
431  #[test]
432  fn test_query_with_empty_values() {
433    let parser = QueryParser::new("flag&empty=").unwrap();
434
435    assert_eq!(parser.get("flag"), Some(""));
436    assert_eq!(parser.get("empty"), Some(""));
437  }
438
439  #[test]
440  fn test_url_encoded_query() {
441    let parser = QueryParser::new("q=hello%20world&name=John%2BDoe&test=hello+world").unwrap();
442
443    assert_eq!(parser.get("q"), Some("hello world"));
444    assert_eq!(parser.get("name"), Some("John+Doe")); // %2B 解码为 +,不是空格
445    assert_eq!(parser.get("test"), Some("hello world")); // + 解码为空格
446  }
447
448  #[test]
449  fn test_query_modification() {
450    let mut parser = QueryParser::new("q=rust").unwrap();
451
452    parser.set("page", 2u32);
453    parser.add("tags", "web");
454    parser.add("tags", "backend");
455
456    assert_eq!(parser.get("page"), Some("2"));
457    assert_eq!(parser.get_all("tags"), &["web", "backend"]);
458
459    parser.remove("q");
460    assert_eq!(parser.get("q"), None);
461  }
462
463  #[test]
464  fn test_query_builder() {
465    let query = QueryBuilder::new()
466      .set("q", "rust")
467      .set("page", 2u32)
468      .add("tags", "web")
469      .add("tags", "backend")
470      .build_string();
471
472    // 验证查询字符串包含所有参数
473    assert!(query.contains("q=rust"));
474    assert!(query.contains("page=2"));
475    assert!(query.contains("tags=web"));
476    assert!(query.contains("tags=backend"));
477  }
478
479  #[test]
480  fn test_contains_and_keys() {
481    let parser = QueryParser::new("q=rust&page=2&tags=web").unwrap();
482
483    assert!(parser.contains("q"));
484    assert!(parser.contains("page"));
485    assert!(parser.contains("tags"));
486    assert!(!parser.contains("missing"));
487
488    let mut keys = parser.keys();
489    keys.sort(); // HashMap 顺序不确定
490    assert_eq!(keys, vec!["page", "q", "tags"]);
491  }
492}