1use std::collections::HashMap;
41
42pub struct QueryParams;
47
48impl QueryParams {
49 pub const PAGE_SIZE: &'static str = "page_size";
52
53 pub const PAGE_TOKEN: &'static str = "page_token";
55
56 pub const PAGE: &'static str = "page";
58
59 pub const OFFSET: &'static str = "offset";
61
62 pub const LIMIT: &'static str = "limit";
64
65 pub const START_TIME: &'static str = "start_time";
68
69 pub const END_TIME: &'static str = "end_time";
71
72 pub const CREATE_TIME_START: &'static str = "create_time_start";
74
75 pub const CREATE_TIME_END: &'static str = "create_time_end";
77
78 pub const UPDATE_TIME_START: &'static str = "update_time_start";
80
81 pub const UPDATE_TIME_END: &'static str = "update_time_end";
83
84 pub const USER_ID: &'static str = "user_id";
87
88 pub const USER_ID_TYPE: &'static str = "user_id_type";
90
91 pub const DEPARTMENT_ID: &'static str = "department_id";
93
94 pub const DEPARTMENT_ID_TYPE: &'static str = "department_id_type";
96
97 pub const ORG_ID: &'static str = "org_id";
99
100 pub const EMPLOYEE_ID: &'static str = "employee_id";
102
103 pub const STATUS: &'static str = "status";
106
107 pub const TYPE: &'static str = "type";
109
110 pub const RULE_TYPE: &'static str = "rule_type";
112
113 pub const ACCESS_TYPE: &'static str = "access_type";
115
116 pub const SORT: &'static str = "sort";
118
119 pub const ORDER: &'static str = "order";
121
122 pub const QUERY: &'static str = "query";
125
126 pub const KEYWORD: &'static str = "keyword";
128
129 pub const NAME: &'static str = "name";
131
132 pub const TITLE: &'static str = "title";
134
135 pub const LANGUAGE: &'static str = "language";
137
138 pub const LOCALE: &'static str = "locale";
140
141 pub const MEETING_ID: &'static str = "meeting_id";
144
145 pub const ROOM_ID: &'static str = "room_id";
147
148 pub const RECORDING_ID: &'static str = "recording_id";
150
151 pub const CUSTOM_WORKPLACE_ID: &'static str = "custom_workplace_id";
154
155 pub const WIDGET_ID: &'static str = "widget_id";
157
158 pub const APP_ID: &'static str = "app_id";
160
161 pub const INCOME_TYPE: &'static str = "income_type";
164 pub const START_DATE: &'static str = "start_date";
166 pub const END_DATE: &'static str = "end_date";
168
169 pub const FILE_ID: &'static str = "file_id";
172
173 pub const DOC_ID: &'static str = "doc_id";
175
176 pub const FOLDER_ID: &'static str = "folder_id";
178
179 pub const FILE_TYPE: &'static str = "file_type";
181
182 pub const MESSAGE_ID: &'static str = "message_id";
185
186 pub const CHAT_ID: &'static str = "chat_id";
188
189 pub const CHANNEL_ID: &'static str = "channel_id";
191
192 pub const DEVICE_ID: &'static str = "device_id";
195
196 pub const ACCESS_METHOD: &'static str = "access_method";
198
199 pub const RESULT: &'static str = "result";
201
202 pub const BADGE_ID: &'static str = "badge_id";
205}
206
207#[derive(Debug, Default)]
226pub struct QueryParamsBuilder {
227 params: HashMap<&'static str, String>,
228}
229
230impl QueryParamsBuilder {
231 pub fn new() -> Self {
233 Self {
234 params: HashMap::new(),
235 }
236 }
237
238 pub fn with_capacity(capacity: usize) -> Self {
240 Self {
241 params: HashMap::with_capacity(capacity),
242 }
243 }
244
245 pub fn page_size(mut self, size: i32) -> Self {
249 self.params.insert(QueryParams::PAGE_SIZE, size.to_string());
250 self
251 }
252
253 pub fn page_token<S: ToString>(mut self, token: S) -> Self {
255 self.params
256 .insert(QueryParams::PAGE_TOKEN, token.to_string());
257 self
258 }
259
260 pub fn page(mut self, page: i32) -> Self {
262 self.params.insert(QueryParams::PAGE, page.to_string());
263 self
264 }
265
266 pub fn offset(mut self, offset: i32) -> Self {
268 self.params.insert(QueryParams::OFFSET, offset.to_string());
269 self
270 }
271
272 pub fn limit(mut self, limit: i32) -> Self {
274 self.params.insert(QueryParams::LIMIT, limit.to_string());
275 self
276 }
277
278 pub fn start_time<S: ToString>(mut self, time: S) -> Self {
282 self.params
283 .insert(QueryParams::START_TIME, time.to_string());
284 self
285 }
286
287 pub fn end_time<S: ToString>(mut self, time: S) -> Self {
289 self.params.insert(QueryParams::END_TIME, time.to_string());
290 self
291 }
292
293 pub fn user_id<S: ToString>(mut self, id: S) -> Self {
297 self.params.insert(QueryParams::USER_ID, id.to_string());
298 self
299 }
300
301 pub fn user_id_type<S: ToString>(mut self, id_type: S) -> Self {
303 self.params
304 .insert(QueryParams::USER_ID_TYPE, id_type.to_string());
305 self
306 }
307
308 pub fn department_id<S: ToString>(mut self, id: S) -> Self {
310 self.params
311 .insert(QueryParams::DEPARTMENT_ID, id.to_string());
312 self
313 }
314
315 pub fn org_id<S: ToString>(mut self, id: S) -> Self {
317 self.params.insert(QueryParams::ORG_ID, id.to_string());
318 self
319 }
320
321 pub fn status<S: ToString>(mut self, status: S) -> Self {
325 self.params.insert(QueryParams::STATUS, status.to_string());
326 self
327 }
328
329 pub fn r#type<S: ToString>(mut self, type_value: S) -> Self {
331 self.params
332 .insert(QueryParams::TYPE, type_value.to_string());
333 self
334 }
335
336 pub fn rule_type<S: ToString>(mut self, rule_type: S) -> Self {
338 self.params
339 .insert(QueryParams::RULE_TYPE, rule_type.to_string());
340 self
341 }
342
343 pub fn access_type<S: ToString>(mut self, access_type: S) -> Self {
345 self.params
346 .insert(QueryParams::ACCESS_TYPE, access_type.to_string());
347 self
348 }
349
350 pub fn custom_static(mut self, key: &'static str, value: String) -> Self {
354 self.params.insert(key, value);
355 self
356 }
357
358 pub fn optional<S: ToString>(mut self, key: &'static str, value: Option<S>) -> Self {
360 if let Some(v) = value {
361 self.params.insert(key, v.to_string());
362 }
363 self
364 }
365
366 pub fn build(self) -> HashMap<String, String> {
368 self.params
370 .into_iter()
371 .map(|(k, v)| (k.to_string(), v))
372 .collect()
373 }
374
375 pub fn build_ref(&self) -> &HashMap<&'static str, String> {
378 &self.params
379 }
380
381 pub fn len(&self) -> usize {
383 self.params.len()
384 }
385
386 pub fn is_empty(&self) -> bool {
388 self.params.is_empty()
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use super::*;
395
396 #[test]
399 fn test_pagination_constants() {
400 assert_eq!(QueryParams::PAGE_SIZE, "page_size");
401 assert_eq!(QueryParams::PAGE_TOKEN, "page_token");
402 assert_eq!(QueryParams::PAGE, "page");
403 assert_eq!(QueryParams::OFFSET, "offset");
404 assert_eq!(QueryParams::LIMIT, "limit");
405 }
406
407 #[test]
408 fn test_time_range_constants() {
409 assert_eq!(QueryParams::START_TIME, "start_time");
410 assert_eq!(QueryParams::END_TIME, "end_time");
411 assert_eq!(QueryParams::CREATE_TIME_START, "create_time_start");
412 assert_eq!(QueryParams::CREATE_TIME_END, "create_time_end");
413 assert_eq!(QueryParams::UPDATE_TIME_START, "update_time_start");
414 assert_eq!(QueryParams::UPDATE_TIME_END, "update_time_end");
415 }
416
417 #[test]
418 fn test_user_identity_constants() {
419 assert_eq!(QueryParams::USER_ID, "user_id");
420 assert_eq!(QueryParams::USER_ID_TYPE, "user_id_type");
421 assert_eq!(QueryParams::DEPARTMENT_ID, "department_id");
422 assert_eq!(QueryParams::DEPARTMENT_ID_TYPE, "department_id_type");
423 assert_eq!(QueryParams::ORG_ID, "org_id");
424 assert_eq!(QueryParams::EMPLOYEE_ID, "employee_id");
425 }
426
427 #[test]
428 fn test_status_type_constants() {
429 assert_eq!(QueryParams::STATUS, "status");
430 assert_eq!(QueryParams::TYPE, "type");
431 assert_eq!(QueryParams::RULE_TYPE, "rule_type");
432 assert_eq!(QueryParams::ACCESS_TYPE, "access_type");
433 assert_eq!(QueryParams::SORT, "sort");
434 assert_eq!(QueryParams::ORDER, "order");
435 }
436
437 #[test]
438 fn test_content_search_constants() {
439 assert_eq!(QueryParams::QUERY, "query");
440 assert_eq!(QueryParams::KEYWORD, "keyword");
441 assert_eq!(QueryParams::NAME, "name");
442 assert_eq!(QueryParams::TITLE, "title");
443 assert_eq!(QueryParams::LANGUAGE, "language");
444 assert_eq!(QueryParams::LOCALE, "locale");
445 }
446
447 #[test]
448 fn test_meeting_vc_constants() {
449 assert_eq!(QueryParams::MEETING_ID, "meeting_id");
450 assert_eq!(QueryParams::ROOM_ID, "room_id");
451 assert_eq!(QueryParams::RECORDING_ID, "recording_id");
452 }
453
454 #[test]
455 fn test_workplace_app_constants() {
456 assert_eq!(QueryParams::CUSTOM_WORKPLACE_ID, "custom_workplace_id");
457 assert_eq!(QueryParams::WIDGET_ID, "widget_id");
458 assert_eq!(QueryParams::APP_ID, "app_id");
459 }
460
461 #[test]
462 fn test_hire_related_constants() {
463 assert_eq!(QueryParams::INCOME_TYPE, "income_type");
464 assert_eq!(QueryParams::START_DATE, "start_date");
465 assert_eq!(QueryParams::END_DATE, "end_date");
466 }
467
468 #[test]
469 fn test_file_document_constants() {
470 assert_eq!(QueryParams::FILE_ID, "file_id");
471 assert_eq!(QueryParams::DOC_ID, "doc_id");
472 assert_eq!(QueryParams::FOLDER_ID, "folder_id");
473 assert_eq!(QueryParams::FILE_TYPE, "file_type");
474 }
475
476 #[test]
477 fn test_message_im_constants() {
478 assert_eq!(QueryParams::MESSAGE_ID, "message_id");
479 assert_eq!(QueryParams::CHAT_ID, "chat_id");
480 assert_eq!(QueryParams::CHANNEL_ID, "channel_id");
481 }
482
483 #[test]
484 fn test_device_access_constants() {
485 assert_eq!(QueryParams::DEVICE_ID, "device_id");
486 assert_eq!(QueryParams::ACCESS_METHOD, "access_method");
487 assert_eq!(QueryParams::RESULT, "result");
488 }
489
490 #[test]
491 fn test_badge_constants() {
492 assert_eq!(QueryParams::BADGE_ID, "badge_id");
493 }
494
495 #[test]
498 fn test_query_params_builder_creation() {
499 let builder = QueryParamsBuilder::new();
500 assert_eq!(builder.len(), 0);
501 assert!(builder.is_empty());
502 }
503
504 #[test]
505 fn test_query_params_builder_default() {
506 let builder: QueryParamsBuilder = Default::default();
507 assert_eq!(builder.len(), 0);
508 assert!(builder.is_empty());
509 }
510
511 #[test]
512 fn test_builder_with_capacity() {
513 let builder = QueryParamsBuilder::with_capacity(5);
514 assert_eq!(builder.len(), 0);
515 assert!(builder.is_empty());
516 }
518
519 #[test]
520 fn test_builder_debug_trait() {
521 let builder = QueryParamsBuilder::new().page_size(10).user_id("test123");
522
523 let debug_str = format!("{:?}", builder);
524 assert!(debug_str.contains("QueryParamsBuilder"));
525 assert!(debug_str.contains("params"));
526 }
527
528 #[test]
531 fn test_pagination_methods() {
532 let params = QueryParamsBuilder::new()
533 .page_size(20)
534 .page_token("token_123")
535 .page(1)
536 .offset(100)
537 .limit(50)
538 .build();
539
540 assert_eq!(params.len(), 5);
541 assert_eq!(params.get("page_size"), Some(&"20".to_string()));
542 assert_eq!(params.get("page_token"), Some(&"token_123".to_string()));
543 assert_eq!(params.get("page"), Some(&"1".to_string()));
544 assert_eq!(params.get("offset"), Some(&"100".to_string()));
545 assert_eq!(params.get("limit"), Some(&"50".to_string()));
546 }
547
548 #[test]
549 fn test_page_size_edge_cases() {
550 let params = QueryParamsBuilder::new().page_size(0).build();
551 assert_eq!(params.get("page_size"), Some(&"0".to_string()));
552
553 let params = QueryParamsBuilder::new().page_size(-1).build();
554 assert_eq!(params.get("page_size"), Some(&"-1".to_string()));
555
556 let params = QueryParamsBuilder::new().page_size(i32::MAX).build();
557 assert_eq!(params.get("page_size"), Some(&i32::MAX.to_string()));
558 }
559
560 #[test]
561 fn test_page_token_different_types() {
562 let params = QueryParamsBuilder::new().page_token("string_token").build();
563 assert_eq!(params.get("page_token"), Some(&"string_token".to_string()));
564
565 let params = QueryParamsBuilder::new()
566 .page_token(String::from("owned_string"))
567 .build();
568 assert_eq!(params.get("page_token"), Some(&"owned_string".to_string()));
569
570 let params = QueryParamsBuilder::new().page_token(123).build();
571 assert_eq!(params.get("page_token"), Some(&"123".to_string()));
572 }
573
574 #[test]
575 fn test_offset_limit_combinations() {
576 let params = QueryParamsBuilder::new().offset(0).limit(10).build();
577 assert_eq!(params.get("offset"), Some(&"0".to_string()));
578 assert_eq!(params.get("limit"), Some(&"10".to_string()));
579
580 let params = QueryParamsBuilder::new().offset(100).limit(0).build();
581 assert_eq!(params.get("offset"), Some(&"100".to_string()));
582 assert_eq!(params.get("limit"), Some(&"0".to_string()));
583 }
584
585 #[test]
588 fn test_time_methods() {
589 let params = QueryParamsBuilder::new()
590 .start_time("2024-01-01T00:00:00Z")
591 .end_time("2024-12-31T23:59:59Z")
592 .build();
593
594 assert_eq!(params.len(), 2);
595 assert_eq!(
596 params.get("start_time"),
597 Some(&"2024-01-01T00:00:00Z".to_string())
598 );
599 assert_eq!(
600 params.get("end_time"),
601 Some(&"2024-12-31T23:59:59Z".to_string())
602 );
603 }
604
605 #[test]
606 fn test_time_methods_different_formats() {
607 let params = QueryParamsBuilder::new()
608 .start_time("1640995200") .end_time("2024-01-01") .build();
611
612 assert_eq!(params.get("start_time"), Some(&"1640995200".to_string()));
613 assert_eq!(params.get("end_time"), Some(&"2024-01-01".to_string()));
614 }
615
616 #[test]
617 fn test_time_methods_empty_strings() {
618 let params = QueryParamsBuilder::new()
619 .start_time("")
620 .end_time("")
621 .build();
622
623 assert_eq!(params.get("start_time"), Some(&"".to_string()));
624 assert_eq!(params.get("end_time"), Some(&"".to_string()));
625 }
626
627 #[test]
630 fn test_user_identity_methods() {
631 let params = QueryParamsBuilder::new()
632 .user_id("user_123")
633 .user_id_type("open_id")
634 .department_id("dept_456")
635 .org_id("org_789")
636 .build();
637
638 assert_eq!(params.len(), 4);
639 assert_eq!(params.get("user_id"), Some(&"user_123".to_string()));
640 assert_eq!(params.get("user_id_type"), Some(&"open_id".to_string()));
641 assert_eq!(params.get("department_id"), Some(&"dept_456".to_string()));
642 assert_eq!(params.get("org_id"), Some(&"org_789".to_string()));
643 }
644
645 #[test]
646 fn test_user_id_type_variants() {
647 let params = QueryParamsBuilder::new().user_id_type("open_id").build();
648 assert_eq!(params.get("user_id_type"), Some(&"open_id".to_string()));
649
650 let params = QueryParamsBuilder::new().user_id_type("union_id").build();
651 assert_eq!(params.get("user_id_type"), Some(&"union_id".to_string()));
652
653 let params = QueryParamsBuilder::new().user_id_type("user_id").build();
654 assert_eq!(params.get("user_id_type"), Some(&"user_id".to_string()));
655 }
656
657 #[test]
658 fn test_user_methods_with_unicode() {
659 let params = QueryParamsBuilder::new()
660 .user_id("用户_123")
661 .department_id("部门_456")
662 .build();
663
664 assert_eq!(params.get("user_id"), Some(&"用户_123".to_string()));
665 assert_eq!(params.get("department_id"), Some(&"部门_456".to_string()));
666 }
667
668 #[test]
671 fn test_status_type_methods() {
672 let params = QueryParamsBuilder::new()
673 .status("active")
674 .r#type("document")
675 .rule_type("approval")
676 .access_type("read")
677 .build();
678
679 assert_eq!(params.len(), 4);
680 assert_eq!(params.get("status"), Some(&"active".to_string()));
681 assert_eq!(params.get("type"), Some(&"document".to_string()));
682 assert_eq!(params.get("rule_type"), Some(&"approval".to_string()));
683 assert_eq!(params.get("access_type"), Some(&"read".to_string()));
684 }
685
686 #[test]
687 fn test_type_method_with_raw_identifier() {
688 let params = QueryParamsBuilder::new().r#type("special_type").build();
690
691 assert_eq!(params.get("type"), Some(&"special_type".to_string()));
692 }
693
694 #[test]
695 fn test_status_variations() {
696 let status_values = ["active", "inactive", "pending", "approved", "rejected"];
697
698 for status in &status_values {
699 let params = QueryParamsBuilder::new().status(*status).build();
700 assert_eq!(params.get("status"), Some(&status.to_string()));
701 }
702 }
703
704 #[test]
707 fn test_custom_static_method() {
708 let params = QueryParamsBuilder::new()
709 .custom_static("custom_param", "custom_value".to_string())
710 .custom_static("another_param", "another_value".to_string())
711 .build();
712
713 assert_eq!(params.len(), 2);
714 assert_eq!(
715 params.get("custom_param"),
716 Some(&"custom_value".to_string())
717 );
718 assert_eq!(
719 params.get("another_param"),
720 Some(&"another_value".to_string())
721 );
722 }
723
724 #[test]
725 fn test_optional_method_with_some() {
726 let params = QueryParamsBuilder::new()
727 .optional(QueryParams::PAGE_SIZE, Some(10))
728 .optional(QueryParams::USER_ID, Some("user123"))
729 .optional(QueryParams::STATUS, Some(String::from("active")))
730 .build();
731
732 assert_eq!(params.len(), 3);
733 assert_eq!(params.get("page_size"), Some(&"10".to_string()));
734 assert_eq!(params.get("user_id"), Some(&"user123".to_string()));
735 assert_eq!(params.get("status"), Some(&"active".to_string()));
736 }
737
738 #[test]
739 fn test_optional_method_with_none() {
740 let params = QueryParamsBuilder::new()
741 .optional(QueryParams::PAGE_SIZE, None::<i32>)
742 .optional(QueryParams::PAGE_TOKEN, None::<String>)
743 .optional(QueryParams::USER_ID, None::<&str>)
744 .build();
745
746 assert_eq!(params.len(), 0);
747 assert!(!params.contains_key("page_size"));
748 assert!(!params.contains_key("page_token"));
749 assert!(!params.contains_key("user_id"));
750 }
751
752 #[test]
753 fn test_optional_method_mixed() {
754 let params = QueryParamsBuilder::new()
755 .optional(QueryParams::PAGE_SIZE, Some(10))
756 .optional(QueryParams::PAGE_TOKEN, None::<String>)
757 .optional(QueryParams::USER_ID, Some("user123"))
758 .optional(QueryParams::STATUS, None::<&str>)
759 .build();
760
761 assert_eq!(params.len(), 2);
762 assert_eq!(params.get("page_size"), Some(&"10".to_string()));
763 assert_eq!(params.get("user_id"), Some(&"user123".to_string()));
764 assert!(!params.contains_key("page_token"));
765 assert!(!params.contains_key("status"));
766 }
767
768 #[test]
771 fn test_build_method() {
772 let builder = QueryParamsBuilder::new().page_size(20).user_id("test_user");
773
774 let params = builder.build();
775
776 assert_eq!(params.len(), 2);
777 assert_eq!(params.get("page_size"), Some(&"20".to_string()));
778 assert_eq!(params.get("user_id"), Some(&"test_user".to_string()));
779
780 let _: HashMap<String, String> = params;
782 }
783
784 #[test]
785 fn test_build_ref_method() {
786 let builder = QueryParamsBuilder::new().page_size(20).user_id("test_user");
787
788 let params_ref = builder.build_ref();
789
790 assert_eq!(params_ref.len(), 2);
791 assert_eq!(
792 params_ref.get(QueryParams::PAGE_SIZE),
793 Some(&"20".to_string())
794 );
795 assert_eq!(
796 params_ref.get(QueryParams::USER_ID),
797 Some(&"test_user".to_string())
798 );
799
800 let _: &HashMap<&'static str, String> = params_ref;
802 }
803
804 #[test]
805 fn test_build_empty() {
806 let params = QueryParamsBuilder::new().build();
807 assert_eq!(params.len(), 0);
808 assert!(params.is_empty());
809 }
810
811 #[test]
812 fn test_build_ref_empty() {
813 let builder = QueryParamsBuilder::new();
814 let params_ref = builder.build_ref();
815 assert_eq!(params_ref.len(), 0);
816 assert!(params_ref.is_empty());
817 }
818
819 #[test]
822 fn test_comprehensive_chaining() {
823 let params = QueryParamsBuilder::new()
824 .page_size(50)
825 .page_token("next_page_123")
826 .start_time("2024-01-01T00:00:00Z")
827 .end_time("2024-12-31T23:59:59Z")
828 .user_id("user_456")
829 .user_id_type("open_id")
830 .status("active")
831 .r#type("document")
832 .custom_static("custom_field", "custom_value".to_string())
833 .optional(QueryParams::LIMIT, Some(100))
834 .optional(QueryParams::OFFSET, None::<i32>)
835 .build();
836
837 assert_eq!(params.len(), 10); assert_eq!(params.get("page_size"), Some(&"50".to_string()));
839 assert_eq!(params.get("page_token"), Some(&"next_page_123".to_string()));
840 assert_eq!(
841 params.get("start_time"),
842 Some(&"2024-01-01T00:00:00Z".to_string())
843 );
844 assert_eq!(
845 params.get("end_time"),
846 Some(&"2024-12-31T23:59:59Z".to_string())
847 );
848 assert_eq!(params.get("user_id"), Some(&"user_456".to_string()));
849 assert_eq!(params.get("user_id_type"), Some(&"open_id".to_string()));
850 assert_eq!(params.get("status"), Some(&"active".to_string()));
851 assert_eq!(params.get("type"), Some(&"document".to_string()));
852 assert_eq!(
853 params.get("custom_field"),
854 Some(&"custom_value".to_string())
855 );
856 assert_eq!(params.get("limit"), Some(&"100".to_string()));
857 assert!(!params.contains_key("offset"));
858 }
859
860 #[test]
861 fn test_method_overwriting() {
862 let params = QueryParamsBuilder::new()
863 .page_size(10)
864 .page_size(20) .user_id("user1")
866 .user_id("user2") .build();
868
869 assert_eq!(params.len(), 2);
870 assert_eq!(params.get("page_size"), Some(&"20".to_string()));
871 assert_eq!(params.get("user_id"), Some(&"user2".to_string()));
872 }
873
874 #[test]
875 fn test_large_chain_building() {
876 let mut builder = QueryParamsBuilder::new();
877
878 builder = builder
880 .page_size(10)
881 .page_token("token")
882 .page(1)
883 .offset(0)
884 .limit(50)
885 .start_time("2024-01-01")
886 .end_time("2024-12-31")
887 .user_id("user123")
888 .user_id_type("open_id")
889 .department_id("dept456")
890 .org_id("org789")
891 .status("active")
892 .r#type("document")
893 .rule_type("approval")
894 .access_type("read")
895 .custom_static("param1", "value1".to_string())
896 .custom_static("param2", "value2".to_string())
897 .optional(QueryParams::LANGUAGE, Some("en"))
898 .optional(QueryParams::LOCALE, Some("en_US"))
899 .optional("extra_param", Some("extra_value"));
900
901 let params = builder.build();
902 assert_eq!(params.len(), 20);
903 }
904
905 #[test]
908 fn test_with_capacity_performance() {
909 let large_capacity = 1000;
910 let builder = QueryParamsBuilder::with_capacity(large_capacity);
911
912 assert_eq!(builder.len(), 0);
914 assert!(builder.is_empty());
915 }
916
917 #[test]
918 fn test_memory_efficiency_static_strings() {
919 let params1 = QueryParamsBuilder::new().page_size(10).build();
920
921 let params2 = QueryParamsBuilder::new().page_size(20).build();
922
923 let key1 = params1.keys().next().unwrap();
925 let key2 = params2.keys().next().unwrap();
926
927 assert_eq!(key1, key2);
928 assert_eq!(key1, "page_size");
929 }
930
931 #[test]
932 fn test_string_conversion_consistency() {
933 let builder = QueryParamsBuilder::new()
934 .page_size(42)
935 .user_id("test_user")
936 .status("active");
937
938 let params_owned = builder.build();
939 let params_ref = {
940 let temp_builder = QueryParamsBuilder::new()
941 .page_size(42)
942 .user_id("test_user")
943 .status("active");
944 temp_builder.build_ref().clone()
946 };
947
948 assert_eq!(params_owned.get("page_size"), Some(&"42".to_string()));
950 assert_eq!(
951 params_ref.get(QueryParams::PAGE_SIZE),
952 Some(&"42".to_string())
953 );
954 }
955
956 #[test]
959 fn test_empty_string_values() {
960 let params = QueryParamsBuilder::new()
961 .page_token("")
962 .user_id("")
963 .status("")
964 .build();
965
966 assert_eq!(params.len(), 3);
967 assert_eq!(params.get("page_token"), Some(&"".to_string()));
968 assert_eq!(params.get("user_id"), Some(&"".to_string()));
969 assert_eq!(params.get("status"), Some(&"".to_string()));
970 }
971
972 #[test]
973 fn test_unicode_and_special_characters() {
974 let params = QueryParamsBuilder::new()
975 .user_id("用户_123_éñ")
976 .page_token("🚀🎯📊")
977 .status("状态_active")
978 .custom_static("unicode_key", "测试值_with_emoji_🧪".to_string())
979 .build();
980
981 assert_eq!(params.get("user_id"), Some(&"用户_123_éñ".to_string()));
982 assert_eq!(params.get("page_token"), Some(&"🚀🎯📊".to_string()));
983 assert_eq!(params.get("status"), Some(&"状态_active".to_string()));
984 assert_eq!(
985 params.get("unicode_key"),
986 Some(&"测试值_with_emoji_🧪".to_string())
987 );
988 }
989
990 #[test]
991 fn test_extreme_numeric_values() {
992 let params = QueryParamsBuilder::new()
993 .page_size(i32::MAX)
994 .offset(i32::MIN)
995 .limit(0)
996 .page(-1)
997 .build();
998
999 assert_eq!(params.get("page_size"), Some(&i32::MAX.to_string()));
1000 assert_eq!(params.get("offset"), Some(&i32::MIN.to_string()));
1001 assert_eq!(params.get("limit"), Some(&"0".to_string()));
1002 assert_eq!(params.get("page"), Some(&"-1".to_string()));
1003 }
1004
1005 #[test]
1006 fn test_very_long_strings() {
1007 let long_string = "a".repeat(10000);
1008 let params = QueryParamsBuilder::new()
1009 .page_token(&long_string)
1010 .user_id(&long_string)
1011 .build();
1012
1013 assert_eq!(params.get("page_token"), Some(&long_string));
1014 assert_eq!(params.get("user_id"), Some(&long_string));
1015 }
1016
1017 #[test]
1018 fn test_builder_is_consumed_by_build() {
1019 let builder = QueryParamsBuilder::new().page_size(10).user_id("test");
1020
1021 let _params = builder.build();
1022 }
1025
1026 #[test]
1027 fn test_optional_with_different_types() {
1028 let params = QueryParamsBuilder::new()
1029 .optional("int_param", Some(42))
1030 .optional("string_param", Some("test"))
1031 .optional("owned_string_param", Some(String::from("owned")))
1032 .optional("none_int", None::<i32>)
1033 .optional("none_string", None::<String>)
1034 .build();
1035
1036 assert_eq!(params.len(), 3);
1037 assert_eq!(params.get("int_param"), Some(&"42".to_string()));
1038 assert_eq!(params.get("string_param"), Some(&"test".to_string()));
1039 assert_eq!(params.get("owned_string_param"), Some(&"owned".to_string()));
1040 assert!(!params.contains_key("none_int"));
1041 assert!(!params.contains_key("none_string"));
1042 }
1043
1044 #[test]
1047 fn test_documentation_example() {
1048 let params = QueryParamsBuilder::new()
1050 .page_size(20)
1051 .page_token("token_123")
1052 .start_time("2024-01-01T00:00:00Z")
1053 .build();
1054
1055 assert_eq!(params.get(QueryParams::PAGE_SIZE), Some(&"20".to_string()));
1056 assert_eq!(
1057 params.get(QueryParams::PAGE_TOKEN),
1058 Some(&"token_123".to_string())
1059 );
1060 assert_eq!(
1061 params.get(QueryParams::START_TIME),
1062 Some(&"2024-01-01T00:00:00Z".to_string())
1063 );
1064 }
1065
1066 #[test]
1067 fn test_static_string_memory_optimization() {
1068 let mut params = HashMap::new();
1070 let value = "20".to_string();
1071
1072 params.insert(QueryParams::PAGE_SIZE, value.clone());
1074 assert_eq!(params.get(QueryParams::PAGE_SIZE), Some(&value));
1075
1076 assert_eq!(QueryParams::PAGE_SIZE, "page_size");
1078
1079 let key1 = QueryParams::PAGE_SIZE;
1081 let key2 = QueryParams::PAGE_SIZE;
1082 assert_eq!(key1.as_ptr(), key2.as_ptr()); }
1084}