1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::path::PathBuf;
4use std::str::FromStr;
5
6use serde::{Deserialize, Serialize};
7
8use crate::common::FileType;
9use crate::utils;
10
11pub type SearchId = u32;
13
14#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
16pub struct SearchQuery {
17 pub target: SearchQueryTarget,
19
20 pub condition: SearchQueryCondition,
22
23 pub paths: Vec<PathBuf>,
25
26 #[serde(default)]
28 pub options: SearchQueryOptions,
29}
30
31impl SearchQuery {
32 pub fn contents<I, T>(
34 condition: SearchQueryCondition,
35 paths: I,
36 options: SearchQueryOptions,
37 ) -> Self
38 where
39 I: IntoIterator<Item = T>,
40 T: Into<PathBuf>,
41 {
42 Self {
43 target: SearchQueryTarget::Contents,
44 condition,
45 paths: paths.into_iter().map(Into::into).collect(),
46 options,
47 }
48 }
49
50 pub fn path<I, T>(
52 condition: SearchQueryCondition,
53 paths: I,
54 options: SearchQueryOptions,
55 ) -> Self
56 where
57 I: IntoIterator<Item = T>,
58 T: Into<PathBuf>,
59 {
60 Self {
61 target: SearchQueryTarget::Path,
62 condition,
63 paths: paths.into_iter().map(Into::into).collect(),
64 options,
65 }
66 }
67}
68
69#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
71#[serde(rename_all = "snake_case")]
72pub enum SearchQueryTarget {
73 Path,
75
76 Contents,
78}
79
80#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
82#[serde(rename_all = "snake_case", deny_unknown_fields, tag = "type")]
83pub enum SearchQueryCondition {
84 Contains { value: String },
86
87 EndsWith { value: String },
89
90 Equals { value: String },
92
93 Or { value: Vec<SearchQueryCondition> },
95
96 Regex { value: String },
98
99 StartsWith { value: String },
101}
102
103impl SearchQueryCondition {
104 pub fn contains(value: impl Into<String>) -> Self {
106 Self::Contains {
107 value: value.into(),
108 }
109 }
110
111 pub fn ends_with(value: impl Into<String>) -> Self {
113 Self::EndsWith {
114 value: value.into(),
115 }
116 }
117
118 pub fn equals(value: impl Into<String>) -> Self {
120 Self::Equals {
121 value: value.into(),
122 }
123 }
124
125 pub fn or<I, C>(value: I) -> Self
127 where
128 I: IntoIterator<Item = C>,
129 C: Into<SearchQueryCondition>,
130 {
131 Self::Or {
132 value: value.into_iter().map(|s| s.into()).collect(),
133 }
134 }
135
136 pub fn regex(value: impl Into<String>) -> Self {
138 Self::Regex {
139 value: value.into(),
140 }
141 }
142
143 pub fn starts_with(value: impl Into<String>) -> Self {
145 Self::StartsWith {
146 value: value.into(),
147 }
148 }
149
150 pub fn to_regex_string(&self) -> String {
152 match self {
153 Self::Contains { value } => regex::escape(value),
154 Self::EndsWith { value } => format!(r"{}$", regex::escape(value)),
155 Self::Equals { value } => format!(r"^{}$", regex::escape(value)),
156 Self::Regex { value } => value.to_string(),
157 Self::StartsWith { value } => format!(r"^{}", regex::escape(value)),
158 Self::Or { value } => {
159 let mut s = String::new();
160 for (i, condition) in value.iter().enumerate() {
161 if i > 0 {
162 s.push('|');
163 }
164 s.push_str(&condition.to_regex_string());
165 }
166 s
167 }
168 }
169 }
170}
171
172impl FromStr for SearchQueryCondition {
173 type Err = std::convert::Infallible;
174
175 fn from_str(s: &str) -> Result<Self, Self::Err> {
177 Ok(Self::regex(s))
178 }
179}
180
181#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
183#[serde(default)]
184pub struct SearchQueryOptions {
185 #[serde(skip_serializing_if = "HashSet::is_empty")]
187 pub allowed_file_types: HashSet<FileType>,
188
189 #[serde(skip_serializing_if = "Option::is_none")]
191 pub include: Option<SearchQueryCondition>,
192
193 #[serde(skip_serializing_if = "Option::is_none")]
196 pub exclude: Option<SearchQueryCondition>,
197
198 #[serde(skip_serializing_if = "utils::is_false")]
208 pub upward: bool,
209
210 #[serde(skip_serializing_if = "utils::is_false")]
212 pub follow_symbolic_links: bool,
213
214 #[serde(skip_serializing_if = "Option::is_none")]
216 pub limit: Option<u64>,
217
218 #[serde(skip_serializing_if = "Option::is_none")]
227 pub max_depth: Option<u64>,
228
229 #[serde(skip_serializing_if = "Option::is_none")]
232 pub pagination: Option<u64>,
233
234 #[serde(skip_serializing_if = "utils::is_false")]
236 pub ignore_hidden: bool,
237
238 #[serde(skip_serializing_if = "utils::is_false")]
241 pub use_ignore_files: bool,
242
243 #[serde(skip_serializing_if = "utils::is_false")]
246 pub use_parent_ignore_files: bool,
247
248 #[serde(skip_serializing_if = "utils::is_false")]
251 pub use_git_ignore_files: bool,
252
253 #[serde(skip_serializing_if = "utils::is_false")]
256 pub use_global_git_ignore_files: bool,
257
258 #[serde(skip_serializing_if = "utils::is_false")]
261 pub use_git_exclude_files: bool,
262}
263
264#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
266#[serde(rename_all = "snake_case", deny_unknown_fields, tag = "type")]
267pub enum SearchQueryMatch {
268 Path(SearchQueryPathMatch),
270
271 Contents(SearchQueryContentsMatch),
273}
274
275impl SearchQueryMatch {
276 pub fn into_path_match(self) -> Option<SearchQueryPathMatch> {
277 match self {
278 Self::Path(x) => Some(x),
279 _ => None,
280 }
281 }
282
283 pub fn into_contents_match(self) -> Option<SearchQueryContentsMatch> {
284 match self {
285 Self::Contents(x) => Some(x),
286 _ => None,
287 }
288 }
289}
290
291#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
293pub struct SearchQueryPathMatch {
294 pub path: PathBuf,
296
297 pub submatches: Vec<SearchQuerySubmatch>,
300}
301
302#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
304pub struct SearchQueryContentsMatch {
305 pub path: PathBuf,
307
308 pub lines: SearchQueryMatchData,
310
311 pub line_number: u64,
313
314 pub absolute_offset: u64,
316
317 pub submatches: Vec<SearchQuerySubmatch>,
320}
321
322#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
323pub struct SearchQuerySubmatch {
324 pub r#match: SearchQueryMatchData,
326
327 pub start: u64,
329
330 pub end: u64,
332}
333
334impl SearchQuerySubmatch {
335 pub fn new(r#match: impl Into<SearchQueryMatchData>, start: u64, end: u64) -> Self {
337 Self {
338 r#match: r#match.into(),
339 start,
340 end,
341 }
342 }
343}
344
345#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
346#[serde(untagged)]
347pub enum SearchQueryMatchData {
348 Bytes(Vec<u8>),
350
351 Text(String),
353}
354
355impl SearchQueryMatchData {
356 pub fn text(value: impl Into<String>) -> Self {
358 Self::Text(value.into())
359 }
360
361 pub fn bytes(value: impl Into<Vec<u8>>) -> Self {
363 Self::Bytes(value.into())
364 }
365
366 pub fn to_str(&self) -> Option<&str> {
368 match self {
369 Self::Text(x) => Some(x),
370 Self::Bytes(x) => std::str::from_utf8(x).ok(),
371 }
372 }
373
374 pub fn to_string_lossy(&self) -> Cow<'_, str> {
377 match self {
378 Self::Text(x) => Cow::Borrowed(x),
379 Self::Bytes(x) => String::from_utf8_lossy(x),
380 }
381 }
382}
383
384impl From<Vec<u8>> for SearchQueryMatchData {
385 fn from(bytes: Vec<u8>) -> Self {
386 Self::Bytes(bytes)
387 }
388}
389
390impl<'a> From<&'a [u8]> for SearchQueryMatchData {
391 fn from(bytes: &'a [u8]) -> Self {
392 Self::Bytes(bytes.to_vec())
393 }
394}
395
396impl From<String> for SearchQueryMatchData {
397 fn from(text: String) -> Self {
398 Self::Text(text)
399 }
400}
401
402impl<'a> From<&'a str> for SearchQueryMatchData {
403 fn from(text: &'a str) -> Self {
404 Self::Text(text.to_string())
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use super::*;
411
412 mod search_query {
413 use super::*;
414
415 #[test]
416 fn should_be_able_to_serialize_to_json() {
417 let query = SearchQuery {
418 target: SearchQueryTarget::Contents,
419 condition: SearchQueryCondition::equals("hello world"),
420 paths: vec![PathBuf::from("path1"), PathBuf::from("path2")],
421 options: SearchQueryOptions::default(),
422 };
423
424 let value = serde_json::to_value(query).unwrap();
425 assert_eq!(
426 value,
427 serde_json::json!({
428 "target": "contents",
429 "condition": {
430 "type": "equals",
431 "value": "hello world",
432 },
433 "paths": ["path1", "path2"],
434 "options": {},
435 })
436 );
437 }
438
439 #[test]
440 fn should_be_able_to_deserialize_from_json() {
441 let value = serde_json::json!({
442 "target": "contents",
443 "condition": {
444 "type": "equals",
445 "value": "hello world",
446 },
447 "paths": ["path1", "path2"],
448 });
449
450 let query: SearchQuery = serde_json::from_value(value).unwrap();
451 assert_eq!(
452 query,
453 SearchQuery {
454 target: SearchQueryTarget::Contents,
455 condition: SearchQueryCondition::equals("hello world"),
456 paths: vec![PathBuf::from("path1"), PathBuf::from("path2")],
457 options: SearchQueryOptions::default(),
458 }
459 );
460 }
461
462 #[test]
463 fn should_be_able_to_serialize_to_msgpack() {
464 let query = SearchQuery {
465 target: SearchQueryTarget::Contents,
466 condition: SearchQueryCondition::equals("hello world"),
467 paths: vec![PathBuf::from("path1"), PathBuf::from("path2")],
468 options: SearchQueryOptions::default(),
469 };
470
471 let _ = rmp_serde::encode::to_vec_named(&query).unwrap();
476 }
477
478 #[test]
479 fn should_be_able_to_deserialize_from_msgpack() {
480 let buf = rmp_serde::encode::to_vec_named(&SearchQuery {
485 target: SearchQueryTarget::Contents,
486 condition: SearchQueryCondition::equals("hello world"),
487 paths: vec![PathBuf::from("path1"), PathBuf::from("path2")],
488 options: SearchQueryOptions::default(),
489 })
490 .unwrap();
491
492 let query: SearchQuery = rmp_serde::decode::from_slice(&buf).unwrap();
493 assert_eq!(
494 query,
495 SearchQuery {
496 target: SearchQueryTarget::Contents,
497 condition: SearchQueryCondition::equals("hello world"),
498 paths: vec![PathBuf::from("path1"), PathBuf::from("path2")],
499 options: SearchQueryOptions::default(),
500 }
501 );
502 }
503 }
504
505 mod search_query_target {
506 use super::*;
507
508 #[test]
509 fn should_be_able_to_serialize_to_json() {
510 let target = SearchQueryTarget::Contents;
511 let value = serde_json::to_value(target).unwrap();
512 assert_eq!(value, serde_json::json!("contents"));
513
514 let target = SearchQueryTarget::Path;
515 let value = serde_json::to_value(target).unwrap();
516 assert_eq!(value, serde_json::json!("path"));
517 }
518
519 #[test]
520 fn should_be_able_to_deserialize_from_json() {
521 let value = serde_json::json!("contents");
522 let target: SearchQueryTarget = serde_json::from_value(value).unwrap();
523 assert_eq!(target, SearchQueryTarget::Contents);
524
525 let value = serde_json::json!("path");
526 let target: SearchQueryTarget = serde_json::from_value(value).unwrap();
527 assert_eq!(target, SearchQueryTarget::Path);
528 }
529
530 #[test]
531 fn should_be_able_to_serialize_to_msgpack() {
532 let target = SearchQueryTarget::Contents;
537 let _ = rmp_serde::encode::to_vec_named(&target).unwrap();
538
539 let target = SearchQueryTarget::Path;
540 let _ = rmp_serde::encode::to_vec_named(&target).unwrap();
541 }
542
543 #[test]
544 fn should_be_able_to_deserialize_from_msgpack() {
545 let buf = rmp_serde::encode::to_vec_named(&SearchQueryTarget::Contents).unwrap();
550 let target: SearchQueryTarget = rmp_serde::decode::from_slice(&buf).unwrap();
551 assert_eq!(target, SearchQueryTarget::Contents);
552
553 let buf = rmp_serde::encode::to_vec_named(&SearchQueryTarget::Path).unwrap();
554 let target: SearchQueryTarget = rmp_serde::decode::from_slice(&buf).unwrap();
555 assert_eq!(target, SearchQueryTarget::Path);
556 }
557 }
558
559 mod search_query_condition {
560 use super::*;
561
562 #[test]
563 fn to_regex_string_should_convert_to_appropriate_regex_and_escape_as_needed() {
564 assert_eq!(
565 SearchQueryCondition::contains("t^es$t").to_regex_string(),
566 r"t\^es\$t"
567 );
568 assert_eq!(
569 SearchQueryCondition::ends_with("t^es$t").to_regex_string(),
570 r"t\^es\$t$"
571 );
572 assert_eq!(
573 SearchQueryCondition::equals("t^es$t").to_regex_string(),
574 r"^t\^es\$t$"
575 );
576 assert_eq!(
577 SearchQueryCondition::or([
578 SearchQueryCondition::contains("t^es$t"),
579 SearchQueryCondition::equals("t^es$t"),
580 SearchQueryCondition::regex("^test$"),
581 ])
582 .to_regex_string(),
583 r"t\^es\$t|^t\^es\$t$|^test$"
584 );
585 assert_eq!(
586 SearchQueryCondition::regex("test").to_regex_string(),
587 "test"
588 );
589 assert_eq!(
590 SearchQueryCondition::starts_with("t^es$t").to_regex_string(),
591 r"^t\^es\$t"
592 );
593 }
594
595 mod contains {
596 use super::*;
597
598 #[test]
599 fn should_be_able_to_serialize_to_json() {
600 let condition = SearchQueryCondition::contains("some text");
601
602 let value = serde_json::to_value(condition).unwrap();
603 assert_eq!(
604 value,
605 serde_json::json!({
606 "type": "contains",
607 "value": "some text",
608 })
609 );
610 }
611
612 #[test]
613 fn should_be_able_to_deserialize_from_json() {
614 let value = serde_json::json!({
615 "type": "contains",
616 "value": "some text",
617 });
618
619 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
620 assert_eq!(condition, SearchQueryCondition::contains("some text"));
621 }
622
623 #[test]
624 fn should_be_able_to_serialize_to_msgpack() {
625 let condition = SearchQueryCondition::contains("some text");
626
627 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
632 }
633
634 #[test]
635 fn should_be_able_to_deserialize_from_msgpack() {
636 let buf =
641 rmp_serde::encode::to_vec_named(&SearchQueryCondition::contains("some text"))
642 .unwrap();
643
644 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
645 assert_eq!(condition, SearchQueryCondition::contains("some text"));
646 }
647 }
648
649 mod ends_with {
650 use super::*;
651
652 #[test]
653 fn should_be_able_to_serialize_to_json() {
654 let condition = SearchQueryCondition::ends_with("some text");
655
656 let value = serde_json::to_value(condition).unwrap();
657 assert_eq!(
658 value,
659 serde_json::json!({
660 "type": "ends_with",
661 "value": "some text",
662 })
663 );
664 }
665
666 #[test]
667 fn should_be_able_to_deserialize_from_json() {
668 let value = serde_json::json!({
669 "type": "ends_with",
670 "value": "some text",
671 });
672
673 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
674 assert_eq!(condition, SearchQueryCondition::ends_with("some text"));
675 }
676
677 #[test]
678 fn should_be_able_to_serialize_to_msgpack() {
679 let condition = SearchQueryCondition::ends_with("some text");
680
681 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
686 }
687
688 #[test]
689 fn should_be_able_to_deserialize_from_msgpack() {
690 let buf =
695 rmp_serde::encode::to_vec_named(&SearchQueryCondition::ends_with("some text"))
696 .unwrap();
697
698 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
699 assert_eq!(condition, SearchQueryCondition::ends_with("some text"));
700 }
701 }
702
703 mod equals {
704 use super::*;
705
706 #[test]
707 fn should_be_able_to_serialize_to_json() {
708 let condition = SearchQueryCondition::equals("some text");
709
710 let value = serde_json::to_value(condition).unwrap();
711 assert_eq!(
712 value,
713 serde_json::json!({
714 "type": "equals",
715 "value": "some text",
716 })
717 );
718 }
719
720 #[test]
721 fn should_be_able_to_deserialize_from_json() {
722 let value = serde_json::json!({
723 "type": "equals",
724 "value": "some text",
725 });
726
727 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
728 assert_eq!(condition, SearchQueryCondition::equals("some text"));
729 }
730
731 #[test]
732 fn should_be_able_to_serialize_to_msgpack() {
733 let condition = SearchQueryCondition::equals("some text");
734
735 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
740 }
741
742 #[test]
743 fn should_be_able_to_deserialize_from_msgpack() {
744 let buf =
749 rmp_serde::encode::to_vec_named(&SearchQueryCondition::equals("some text"))
750 .unwrap();
751
752 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
753 assert_eq!(condition, SearchQueryCondition::equals("some text"));
754 }
755 }
756
757 mod or {
758 use super::*;
759
760 #[test]
761 fn should_be_able_to_serialize_to_json() {
762 let condition = SearchQueryCondition::or([
763 SearchQueryCondition::starts_with("start text"),
764 SearchQueryCondition::ends_with("end text"),
765 ]);
766
767 let value = serde_json::to_value(condition).unwrap();
768 assert_eq!(
769 value,
770 serde_json::json!({
771 "type": "or",
772 "value": [
773 { "type": "starts_with", "value": "start text" },
774 { "type": "ends_with", "value": "end text" },
775 ],
776 })
777 );
778 }
779
780 #[test]
781 fn should_be_able_to_deserialize_from_json() {
782 let value = serde_json::json!({
783 "type": "or",
784 "value": [
785 { "type": "starts_with", "value": "start text" },
786 { "type": "ends_with", "value": "end text" },
787 ],
788 });
789
790 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
791 assert_eq!(
792 condition,
793 SearchQueryCondition::or([
794 SearchQueryCondition::starts_with("start text"),
795 SearchQueryCondition::ends_with("end text"),
796 ])
797 );
798 }
799
800 #[test]
801 fn should_be_able_to_serialize_to_msgpack() {
802 let condition = SearchQueryCondition::or([
803 SearchQueryCondition::starts_with("start text"),
804 SearchQueryCondition::ends_with("end text"),
805 ]);
806
807 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
812 }
813
814 #[test]
815 fn should_be_able_to_deserialize_from_msgpack() {
816 let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::or([
821 SearchQueryCondition::starts_with("start text"),
822 SearchQueryCondition::ends_with("end text"),
823 ]))
824 .unwrap();
825
826 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
827 assert_eq!(
828 condition,
829 SearchQueryCondition::or([
830 SearchQueryCondition::starts_with("start text"),
831 SearchQueryCondition::ends_with("end text"),
832 ])
833 );
834 }
835 }
836
837 mod regex {
838 use super::*;
839
840 #[test]
841 fn should_be_able_to_serialize_to_json() {
842 let condition = SearchQueryCondition::regex("some text");
843
844 let value = serde_json::to_value(condition).unwrap();
845 assert_eq!(
846 value,
847 serde_json::json!({
848 "type": "regex",
849 "value": "some text",
850 })
851 );
852 }
853
854 #[test]
855 fn should_be_able_to_deserialize_from_json() {
856 let value = serde_json::json!({
857 "type": "regex",
858 "value": "some text",
859 });
860
861 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
862 assert_eq!(condition, SearchQueryCondition::regex("some text"));
863 }
864
865 #[test]
866 fn should_be_able_to_serialize_to_msgpack() {
867 let condition = SearchQueryCondition::regex("some text");
868
869 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
874 }
875
876 #[test]
877 fn should_be_able_to_deserialize_from_msgpack() {
878 let buf =
883 rmp_serde::encode::to_vec_named(&SearchQueryCondition::regex("some text"))
884 .unwrap();
885
886 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
887 assert_eq!(condition, SearchQueryCondition::regex("some text"));
888 }
889 }
890
891 mod starts_with {
892 use super::*;
893
894 #[test]
895 fn should_be_able_to_serialize_to_json() {
896 let condition = SearchQueryCondition::starts_with("some text");
897
898 let value = serde_json::to_value(condition).unwrap();
899 assert_eq!(
900 value,
901 serde_json::json!({
902 "type": "starts_with",
903 "value": "some text",
904 })
905 );
906 }
907
908 #[test]
909 fn should_be_able_to_deserialize_from_json() {
910 let value = serde_json::json!({
911 "type": "starts_with",
912 "value": "some text",
913 });
914
915 let condition: SearchQueryCondition = serde_json::from_value(value).unwrap();
916 assert_eq!(condition, SearchQueryCondition::starts_with("some text"));
917 }
918
919 #[test]
920 fn should_be_able_to_serialize_to_msgpack() {
921 let condition = SearchQueryCondition::starts_with("some text");
922
923 let _ = rmp_serde::encode::to_vec_named(&condition).unwrap();
928 }
929
930 #[test]
931 fn should_be_able_to_deserialize_from_msgpack() {
932 let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::starts_with(
937 "some text",
938 ))
939 .unwrap();
940
941 let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap();
942 assert_eq!(condition, SearchQueryCondition::starts_with("some text"));
943 }
944 }
945 }
946
947 mod search_query_options {
948 use super::*;
949
950 #[test]
951 fn should_be_able_to_serialize_minimal_options_to_json() {
952 let options = SearchQueryOptions {
953 allowed_file_types: [].into_iter().collect(),
954 include: None,
955 exclude: None,
956 upward: false,
957 follow_symbolic_links: false,
958 limit: None,
959 max_depth: None,
960 pagination: None,
961 ignore_hidden: false,
962 use_ignore_files: false,
963 use_parent_ignore_files: false,
964 use_git_ignore_files: false,
965 use_global_git_ignore_files: false,
966 use_git_exclude_files: false,
967 };
968
969 let value = serde_json::to_value(options).unwrap();
970 assert_eq!(value, serde_json::json!({}));
971 }
972
973 #[test]
974 fn should_be_able_to_serialize_full_options_to_json() {
975 let options = SearchQueryOptions {
976 allowed_file_types: [FileType::File].into_iter().collect(),
977 include: Some(SearchQueryCondition::Equals {
978 value: String::from("hello"),
979 }),
980 exclude: Some(SearchQueryCondition::Contains {
981 value: String::from("world"),
982 }),
983 upward: true,
984 follow_symbolic_links: true,
985 limit: Some(u64::MAX),
986 max_depth: Some(u64::MAX),
987 pagination: Some(u64::MAX),
988 ignore_hidden: true,
989 use_ignore_files: true,
990 use_parent_ignore_files: true,
991 use_git_ignore_files: true,
992 use_global_git_ignore_files: true,
993 use_git_exclude_files: true,
994 };
995
996 let value = serde_json::to_value(options).unwrap();
997 assert_eq!(
998 value,
999 serde_json::json!({
1000 "allowed_file_types": ["file"],
1001 "include": {
1002 "type": "equals",
1003 "value": "hello",
1004 },
1005 "exclude": {
1006 "type": "contains",
1007 "value": "world",
1008 },
1009 "upward": true,
1010 "follow_symbolic_links": true,
1011 "limit": u64::MAX,
1012 "max_depth": u64::MAX,
1013 "pagination": u64::MAX,
1014 "ignore_hidden": true,
1015 "use_ignore_files": true,
1016 "use_parent_ignore_files": true,
1017 "use_git_ignore_files": true,
1018 "use_global_git_ignore_files": true,
1019 "use_git_exclude_files": true,
1020 })
1021 );
1022 }
1023
1024 #[test]
1025 fn should_be_able_to_deserialize_minimal_options_from_json() {
1026 let value = serde_json::json!({});
1027
1028 let options: SearchQueryOptions = serde_json::from_value(value).unwrap();
1029 assert_eq!(
1030 options,
1031 SearchQueryOptions {
1032 allowed_file_types: [].into_iter().collect(),
1033 include: None,
1034 exclude: None,
1035 upward: false,
1036 follow_symbolic_links: false,
1037 limit: None,
1038 max_depth: None,
1039 pagination: None,
1040 ignore_hidden: false,
1041 use_ignore_files: false,
1042 use_parent_ignore_files: false,
1043 use_git_ignore_files: false,
1044 use_global_git_ignore_files: false,
1045 use_git_exclude_files: false,
1046 }
1047 );
1048 }
1049
1050 #[test]
1051 fn should_be_able_to_deserialize_full_options_from_json() {
1052 let value = serde_json::json!({
1053 "allowed_file_types": ["file"],
1054 "include": {
1055 "type": "equals",
1056 "value": "hello",
1057 },
1058 "exclude": {
1059 "type": "contains",
1060 "value": "world",
1061 },
1062 "upward": true,
1063 "follow_symbolic_links": true,
1064 "limit": u64::MAX,
1065 "max_depth": u64::MAX,
1066 "pagination": u64::MAX,
1067 "ignore_hidden": true,
1068 "use_ignore_files": true,
1069 "use_parent_ignore_files": true,
1070 "use_git_ignore_files": true,
1071 "use_global_git_ignore_files": true,
1072 "use_git_exclude_files": true,
1073 });
1074
1075 let options: SearchQueryOptions = serde_json::from_value(value).unwrap();
1076 assert_eq!(
1077 options,
1078 SearchQueryOptions {
1079 allowed_file_types: [FileType::File].into_iter().collect(),
1080 include: Some(SearchQueryCondition::Equals {
1081 value: String::from("hello"),
1082 }),
1083 exclude: Some(SearchQueryCondition::Contains {
1084 value: String::from("world"),
1085 }),
1086 upward: true,
1087 follow_symbolic_links: true,
1088 limit: Some(u64::MAX),
1089 max_depth: Some(u64::MAX),
1090 pagination: Some(u64::MAX),
1091 ignore_hidden: true,
1092 use_ignore_files: true,
1093 use_parent_ignore_files: true,
1094 use_git_ignore_files: true,
1095 use_global_git_ignore_files: true,
1096 use_git_exclude_files: true,
1097 }
1098 );
1099 }
1100
1101 #[test]
1102 fn should_be_able_to_serialize_minimal_options_to_msgpack() {
1103 let options = SearchQueryOptions {
1104 allowed_file_types: [].into_iter().collect(),
1105 include: None,
1106 exclude: None,
1107 upward: false,
1108 follow_symbolic_links: false,
1109 limit: None,
1110 max_depth: None,
1111 pagination: None,
1112 ignore_hidden: false,
1113 use_ignore_files: false,
1114 use_parent_ignore_files: false,
1115 use_git_ignore_files: false,
1116 use_global_git_ignore_files: false,
1117 use_git_exclude_files: false,
1118 };
1119
1120 let _ = rmp_serde::encode::to_vec_named(&options).unwrap();
1125 }
1126
1127 #[test]
1128 fn should_be_able_to_serialize_full_options_to_msgpack() {
1129 let options = SearchQueryOptions {
1130 allowed_file_types: [FileType::File].into_iter().collect(),
1131 include: Some(SearchQueryCondition::Equals {
1132 value: String::from("hello"),
1133 }),
1134 exclude: Some(SearchQueryCondition::Contains {
1135 value: String::from("world"),
1136 }),
1137 upward: true,
1138 follow_symbolic_links: true,
1139 limit: Some(u64::MAX),
1140 max_depth: Some(u64::MAX),
1141 pagination: Some(u64::MAX),
1142 ignore_hidden: true,
1143 use_ignore_files: true,
1144 use_parent_ignore_files: true,
1145 use_git_ignore_files: true,
1146 use_global_git_ignore_files: true,
1147 use_git_exclude_files: true,
1148 };
1149
1150 let _ = rmp_serde::encode::to_vec_named(&options).unwrap();
1155 }
1156
1157 #[test]
1158 fn should_be_able_to_deserialize_minimal_options_from_msgpack() {
1159 let buf = rmp_serde::encode::to_vec_named(&SearchQueryOptions {
1164 allowed_file_types: [].into_iter().collect(),
1165 include: None,
1166 exclude: None,
1167 upward: false,
1168 follow_symbolic_links: false,
1169 limit: None,
1170 max_depth: None,
1171 pagination: None,
1172 ignore_hidden: false,
1173 use_ignore_files: false,
1174 use_parent_ignore_files: false,
1175 use_git_ignore_files: false,
1176 use_global_git_ignore_files: false,
1177 use_git_exclude_files: false,
1178 })
1179 .unwrap();
1180
1181 let options: SearchQueryOptions = rmp_serde::decode::from_slice(&buf).unwrap();
1182 assert_eq!(
1183 options,
1184 SearchQueryOptions {
1185 allowed_file_types: [].into_iter().collect(),
1186 include: None,
1187 exclude: None,
1188 upward: false,
1189 follow_symbolic_links: false,
1190 limit: None,
1191 max_depth: None,
1192 pagination: None,
1193 ignore_hidden: false,
1194 use_ignore_files: false,
1195 use_parent_ignore_files: false,
1196 use_git_ignore_files: false,
1197 use_global_git_ignore_files: false,
1198 use_git_exclude_files: false,
1199 }
1200 );
1201 }
1202
1203 #[test]
1204 fn should_be_able_to_deserialize_full_options_from_msgpack() {
1205 let buf = rmp_serde::encode::to_vec_named(&SearchQueryOptions {
1210 allowed_file_types: [FileType::File].into_iter().collect(),
1211 include: Some(SearchQueryCondition::Equals {
1212 value: String::from("hello"),
1213 }),
1214 exclude: Some(SearchQueryCondition::Contains {
1215 value: String::from("world"),
1216 }),
1217 upward: true,
1218 follow_symbolic_links: true,
1219 limit: Some(u64::MAX),
1220 max_depth: Some(u64::MAX),
1221 pagination: Some(u64::MAX),
1222 ignore_hidden: true,
1223 use_ignore_files: true,
1224 use_parent_ignore_files: true,
1225 use_git_ignore_files: true,
1226 use_global_git_ignore_files: true,
1227 use_git_exclude_files: true,
1228 })
1229 .unwrap();
1230
1231 let options: SearchQueryOptions = rmp_serde::decode::from_slice(&buf).unwrap();
1232 assert_eq!(
1233 options,
1234 SearchQueryOptions {
1235 allowed_file_types: [FileType::File].into_iter().collect(),
1236 include: Some(SearchQueryCondition::Equals {
1237 value: String::from("hello"),
1238 }),
1239 exclude: Some(SearchQueryCondition::Contains {
1240 value: String::from("world"),
1241 }),
1242 upward: true,
1243 follow_symbolic_links: true,
1244 limit: Some(u64::MAX),
1245 max_depth: Some(u64::MAX),
1246 pagination: Some(u64::MAX),
1247 ignore_hidden: true,
1248 use_ignore_files: true,
1249 use_parent_ignore_files: true,
1250 use_git_ignore_files: true,
1251 use_global_git_ignore_files: true,
1252 use_git_exclude_files: true,
1253 }
1254 );
1255 }
1256 }
1257
1258 mod search_query_match {
1259 use super::*;
1260
1261 mod for_path {
1262 use super::*;
1263
1264 #[test]
1265 fn should_be_able_to_serialize_to_json() {
1266 let r#match = SearchQueryMatch::Path(SearchQueryPathMatch {
1267 path: PathBuf::from("path"),
1268 submatches: vec![SearchQuerySubmatch {
1269 r#match: SearchQueryMatchData::Text(String::from("text")),
1270 start: 8,
1271 end: 13,
1272 }],
1273 });
1274
1275 let value = serde_json::to_value(r#match).unwrap();
1276 assert_eq!(
1277 value,
1278 serde_json::json!({
1279 "type": "path",
1280 "path": "path",
1281 "submatches": [{
1282 "match": "text",
1283 "start": 8,
1284 "end": 13,
1285 }],
1286 })
1287 );
1288 }
1289
1290 #[test]
1291 fn should_be_able_to_deserialize_from_json() {
1292 let value = serde_json::json!({
1293 "type": "path",
1294 "path": "path",
1295 "submatches": [{
1296 "match": "text",
1297 "start": 8,
1298 "end": 13,
1299 }],
1300 });
1301
1302 let r#match: SearchQueryMatch = serde_json::from_value(value).unwrap();
1303 assert_eq!(
1304 r#match,
1305 SearchQueryMatch::Path(SearchQueryPathMatch {
1306 path: PathBuf::from("path"),
1307 submatches: vec![SearchQuerySubmatch {
1308 r#match: SearchQueryMatchData::Text(String::from("text")),
1309 start: 8,
1310 end: 13,
1311 }],
1312 })
1313 );
1314 }
1315
1316 #[test]
1317 fn should_be_able_to_serialize_to_msgpack() {
1318 let r#match = SearchQueryMatch::Path(SearchQueryPathMatch {
1319 path: PathBuf::from("path"),
1320 submatches: vec![SearchQuerySubmatch {
1321 r#match: SearchQueryMatchData::Text(String::from("text")),
1322 start: 8,
1323 end: 13,
1324 }],
1325 });
1326
1327 let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap();
1332 }
1333
1334 #[test]
1335 fn should_be_able_to_deserialize_from_msgpack() {
1336 let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatch::Path(
1341 SearchQueryPathMatch {
1342 path: PathBuf::from("path"),
1343 submatches: vec![SearchQuerySubmatch {
1344 r#match: SearchQueryMatchData::Text(String::from("text")),
1345 start: 8,
1346 end: 13,
1347 }],
1348 },
1349 ))
1350 .unwrap();
1351
1352 let r#match: SearchQueryMatch = rmp_serde::decode::from_slice(&buf).unwrap();
1353 assert_eq!(
1354 r#match,
1355 SearchQueryMatch::Path(SearchQueryPathMatch {
1356 path: PathBuf::from("path"),
1357 submatches: vec![SearchQuerySubmatch {
1358 r#match: SearchQueryMatchData::Text(String::from("text")),
1359 start: 8,
1360 end: 13,
1361 }],
1362 })
1363 );
1364 }
1365 }
1366
1367 mod for_contents {
1368 use super::*;
1369
1370 #[test]
1371 fn should_be_able_to_serialize_to_json() {
1372 let r#match = SearchQueryMatch::Contents(SearchQueryContentsMatch {
1373 path: PathBuf::from("path"),
1374 lines: SearchQueryMatchData::Text(String::from("some text")),
1375 line_number: 12,
1376 absolute_offset: 24,
1377 submatches: vec![SearchQuerySubmatch {
1378 r#match: SearchQueryMatchData::Text(String::from("text")),
1379 start: 8,
1380 end: 13,
1381 }],
1382 });
1383
1384 let value = serde_json::to_value(r#match).unwrap();
1385 assert_eq!(
1386 value,
1387 serde_json::json!({
1388 "type": "contents",
1389 "path": "path",
1390 "lines": "some text",
1391 "line_number": 12,
1392 "absolute_offset": 24,
1393 "submatches": [{
1394 "match": "text",
1395 "start": 8,
1396 "end": 13,
1397 }],
1398 })
1399 );
1400 }
1401
1402 #[test]
1403 fn should_be_able_to_deserialize_from_json() {
1404 let value = serde_json::json!({
1405 "type": "contents",
1406 "path": "path",
1407 "lines": "some text",
1408 "line_number": 12,
1409 "absolute_offset": 24,
1410 "submatches": [{
1411 "match": "text",
1412 "start": 8,
1413 "end": 13,
1414 }],
1415 });
1416
1417 let r#match: SearchQueryMatch = serde_json::from_value(value).unwrap();
1418 assert_eq!(
1419 r#match,
1420 SearchQueryMatch::Contents(SearchQueryContentsMatch {
1421 path: PathBuf::from("path"),
1422 lines: SearchQueryMatchData::Text(String::from("some text")),
1423 line_number: 12,
1424 absolute_offset: 24,
1425 submatches: vec![SearchQuerySubmatch {
1426 r#match: SearchQueryMatchData::Text(String::from("text")),
1427 start: 8,
1428 end: 13,
1429 }],
1430 })
1431 );
1432 }
1433
1434 #[test]
1435 fn should_be_able_to_serialize_to_msgpack() {
1436 let r#match = SearchQueryMatch::Contents(SearchQueryContentsMatch {
1437 path: PathBuf::from("path"),
1438 lines: SearchQueryMatchData::Text(String::from("some text")),
1439 line_number: 12,
1440 absolute_offset: 24,
1441 submatches: vec![SearchQuerySubmatch {
1442 r#match: SearchQueryMatchData::Text(String::from("text")),
1443 start: 8,
1444 end: 13,
1445 }],
1446 });
1447
1448 let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap();
1453 }
1454
1455 #[test]
1456 fn should_be_able_to_deserialize_from_msgpack() {
1457 let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatch::Contents(
1462 SearchQueryContentsMatch {
1463 path: PathBuf::from("path"),
1464 lines: SearchQueryMatchData::Text(String::from("some text")),
1465 line_number: 12,
1466 absolute_offset: 24,
1467 submatches: vec![SearchQuerySubmatch {
1468 r#match: SearchQueryMatchData::Text(String::from("text")),
1469 start: 8,
1470 end: 13,
1471 }],
1472 },
1473 ))
1474 .unwrap();
1475
1476 let r#match: SearchQueryMatch = rmp_serde::decode::from_slice(&buf).unwrap();
1477 assert_eq!(
1478 r#match,
1479 SearchQueryMatch::Contents(SearchQueryContentsMatch {
1480 path: PathBuf::from("path"),
1481 lines: SearchQueryMatchData::Text(String::from("some text")),
1482 line_number: 12,
1483 absolute_offset: 24,
1484 submatches: vec![SearchQuerySubmatch {
1485 r#match: SearchQueryMatchData::Text(String::from("text")),
1486 start: 8,
1487 end: 13,
1488 }],
1489 })
1490 );
1491 }
1492 }
1493 }
1494
1495 mod search_query_path_match {
1496 use super::*;
1497
1498 #[test]
1499 fn should_be_able_to_serialize_to_json() {
1500 let r#match = SearchQueryPathMatch {
1501 path: PathBuf::from("path"),
1502 submatches: vec![SearchQuerySubmatch {
1503 r#match: SearchQueryMatchData::Text(String::from("text")),
1504 start: 8,
1505 end: 13,
1506 }],
1507 };
1508
1509 let value = serde_json::to_value(r#match).unwrap();
1510 assert_eq!(
1511 value,
1512 serde_json::json!({
1513 "path": "path",
1514 "submatches": [{
1515 "match": "text",
1516 "start": 8,
1517 "end": 13,
1518 }],
1519 })
1520 );
1521 }
1522
1523 #[test]
1524 fn should_be_able_to_deserialize_from_json() {
1525 let value = serde_json::json!({
1526 "path": "path",
1527 "submatches": [{
1528 "match": "text",
1529 "start": 8,
1530 "end": 13,
1531 }],
1532 });
1533
1534 let r#match: SearchQueryPathMatch = serde_json::from_value(value).unwrap();
1535 assert_eq!(
1536 r#match,
1537 SearchQueryPathMatch {
1538 path: PathBuf::from("path"),
1539 submatches: vec![SearchQuerySubmatch {
1540 r#match: SearchQueryMatchData::Text(String::from("text")),
1541 start: 8,
1542 end: 13,
1543 }],
1544 }
1545 );
1546 }
1547
1548 #[test]
1549 fn should_be_able_to_serialize_to_msgpack() {
1550 let r#match = SearchQueryPathMatch {
1551 path: PathBuf::from("path"),
1552 submatches: vec![SearchQuerySubmatch {
1553 r#match: SearchQueryMatchData::Text(String::from("text")),
1554 start: 8,
1555 end: 13,
1556 }],
1557 };
1558
1559 let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap();
1564 }
1565
1566 #[test]
1567 fn should_be_able_to_deserialize_from_msgpack() {
1568 let buf = rmp_serde::encode::to_vec_named(&SearchQueryPathMatch {
1573 path: PathBuf::from("path"),
1574 submatches: vec![SearchQuerySubmatch {
1575 r#match: SearchQueryMatchData::Text(String::from("text")),
1576 start: 8,
1577 end: 13,
1578 }],
1579 })
1580 .unwrap();
1581
1582 let r#match: SearchQueryPathMatch = rmp_serde::decode::from_slice(&buf).unwrap();
1583 assert_eq!(
1584 r#match,
1585 SearchQueryPathMatch {
1586 path: PathBuf::from("path"),
1587 submatches: vec![SearchQuerySubmatch {
1588 r#match: SearchQueryMatchData::Text(String::from("text")),
1589 start: 8,
1590 end: 13,
1591 }],
1592 }
1593 );
1594 }
1595 }
1596
1597 mod search_query_contents_match {
1598 use super::*;
1599
1600 #[test]
1601 fn should_be_able_to_serialize_to_json() {
1602 let r#match = SearchQueryContentsMatch {
1603 path: PathBuf::from("path"),
1604 lines: SearchQueryMatchData::Text(String::from("some text")),
1605 line_number: 12,
1606 absolute_offset: 24,
1607 submatches: vec![SearchQuerySubmatch {
1608 r#match: SearchQueryMatchData::Text(String::from("text")),
1609 start: 8,
1610 end: 13,
1611 }],
1612 };
1613
1614 let value = serde_json::to_value(r#match).unwrap();
1615 assert_eq!(
1616 value,
1617 serde_json::json!({
1618 "path": "path",
1619 "lines": "some text",
1620 "line_number": 12,
1621 "absolute_offset": 24,
1622 "submatches": [{
1623 "match": "text",
1624 "start": 8,
1625 "end": 13,
1626 }],
1627 })
1628 );
1629 }
1630
1631 #[test]
1632 fn should_be_able_to_deserialize_from_json() {
1633 let value = serde_json::json!({
1634 "path": "path",
1635 "lines": "some text",
1636 "line_number": 12,
1637 "absolute_offset": 24,
1638 "submatches": [{
1639 "match": "text",
1640 "start": 8,
1641 "end": 13,
1642 }],
1643 });
1644
1645 let r#match: SearchQueryContentsMatch = serde_json::from_value(value).unwrap();
1646 assert_eq!(
1647 r#match,
1648 SearchQueryContentsMatch {
1649 path: PathBuf::from("path"),
1650 lines: SearchQueryMatchData::Text(String::from("some text")),
1651 line_number: 12,
1652 absolute_offset: 24,
1653 submatches: vec![SearchQuerySubmatch {
1654 r#match: SearchQueryMatchData::Text(String::from("text")),
1655 start: 8,
1656 end: 13,
1657 }],
1658 }
1659 );
1660 }
1661
1662 #[test]
1663 fn should_be_able_to_serialize_to_msgpack() {
1664 let r#match = SearchQueryContentsMatch {
1665 path: PathBuf::from("path"),
1666 lines: SearchQueryMatchData::Text(String::from("some text")),
1667 line_number: 12,
1668 absolute_offset: 24,
1669 submatches: vec![SearchQuerySubmatch {
1670 r#match: SearchQueryMatchData::Text(String::from("text")),
1671 start: 8,
1672 end: 13,
1673 }],
1674 };
1675
1676 let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap();
1681 }
1682
1683 #[test]
1684 fn should_be_able_to_deserialize_from_msgpack() {
1685 let buf = rmp_serde::encode::to_vec_named(&SearchQueryContentsMatch {
1690 path: PathBuf::from("path"),
1691 lines: SearchQueryMatchData::Text(String::from("some text")),
1692 line_number: 12,
1693 absolute_offset: 24,
1694 submatches: vec![SearchQuerySubmatch {
1695 r#match: SearchQueryMatchData::Text(String::from("text")),
1696 start: 8,
1697 end: 13,
1698 }],
1699 })
1700 .unwrap();
1701
1702 let r#match: SearchQueryContentsMatch = rmp_serde::decode::from_slice(&buf).unwrap();
1703 assert_eq!(
1704 r#match,
1705 SearchQueryContentsMatch {
1706 path: PathBuf::from("path"),
1707 lines: SearchQueryMatchData::Text(String::from("some text")),
1708 line_number: 12,
1709 absolute_offset: 24,
1710 submatches: vec![SearchQuerySubmatch {
1711 r#match: SearchQueryMatchData::Text(String::from("text")),
1712 start: 8,
1713 end: 13,
1714 }],
1715 }
1716 );
1717 }
1718 }
1719
1720 mod search_query_submatch {
1721 use super::*;
1722
1723 #[test]
1724 fn should_be_able_to_serialize_to_json() {
1725 let data = SearchQuerySubmatch {
1726 r#match: SearchQueryMatchData::Text(String::from("some text")),
1727 start: 12,
1728 end: 24,
1729 };
1730
1731 let value = serde_json::to_value(data).unwrap();
1732 assert_eq!(
1733 value,
1734 serde_json::json!({
1735 "match": "some text",
1736 "start": 12,
1737 "end": 24,
1738 })
1739 );
1740
1741 let data = SearchQuerySubmatch {
1742 r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]),
1743 start: 12,
1744 end: 24,
1745 };
1746
1747 let value = serde_json::to_value(data).unwrap();
1749 assert_eq!(
1750 value,
1751 serde_json::json!({
1752 "match": [1, 2, 3],
1753 "start": 12,
1754 "end": 24,
1755 })
1756 );
1757 }
1758
1759 #[test]
1760 fn should_be_able_to_deserialize_from_json() {
1761 let value = serde_json::json!({
1762 "match": "some text",
1763 "start": 12,
1764 "end": 24,
1765 });
1766
1767 let submatch: SearchQuerySubmatch = serde_json::from_value(value).unwrap();
1768 assert_eq!(
1769 submatch,
1770 SearchQuerySubmatch {
1771 r#match: SearchQueryMatchData::Text(String::from("some text")),
1772 start: 12,
1773 end: 24,
1774 }
1775 );
1776
1777 let value = serde_json::json!({
1779 "match": [1, 2, 3],
1780 "start": 12,
1781 "end": 24,
1782 });
1783
1784 let submatch: SearchQuerySubmatch = serde_json::from_value(value).unwrap();
1785 assert_eq!(
1786 submatch,
1787 SearchQuerySubmatch {
1788 r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]),
1789 start: 12,
1790 end: 24,
1791 }
1792 );
1793 }
1794
1795 #[test]
1796 fn should_be_able_to_serialize_to_msgpack() {
1797 let submatch = SearchQuerySubmatch {
1798 r#match: SearchQueryMatchData::Text(String::from("some text")),
1799 start: 12,
1800 end: 24,
1801 };
1802
1803 let _ = rmp_serde::encode::to_vec_named(&submatch).unwrap();
1808
1809 let submatch = SearchQuerySubmatch {
1811 r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]),
1812 start: 12,
1813 end: 24,
1814 };
1815
1816 let _ = rmp_serde::encode::to_vec_named(&submatch).unwrap();
1817 }
1818
1819 #[test]
1820 fn should_be_able_to_deserialize_from_msgpack() {
1821 let buf = rmp_serde::encode::to_vec_named(&SearchQuerySubmatch {
1826 r#match: SearchQueryMatchData::Text(String::from("some text")),
1827 start: 12,
1828 end: 24,
1829 })
1830 .unwrap();
1831
1832 let submatch: SearchQuerySubmatch = rmp_serde::decode::from_slice(&buf).unwrap();
1833 assert_eq!(
1834 submatch,
1835 SearchQuerySubmatch {
1836 r#match: SearchQueryMatchData::Text(String::from("some text")),
1837 start: 12,
1838 end: 24,
1839 }
1840 );
1841
1842 let buf = rmp_serde::encode::to_vec_named(&SearchQuerySubmatch {
1844 r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]),
1845 start: 12,
1846 end: 24,
1847 })
1848 .unwrap();
1849
1850 let submatch: SearchQuerySubmatch = rmp_serde::decode::from_slice(&buf).unwrap();
1851 assert_eq!(
1852 submatch,
1853 SearchQuerySubmatch {
1854 r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]),
1855 start: 12,
1856 end: 24,
1857 }
1858 );
1859 }
1860 }
1861
1862 mod search_query_match_data {
1863 use super::*;
1864
1865 #[test]
1866 fn should_be_able_to_serialize_to_json() {
1867 let data = SearchQueryMatchData::Text(String::from("some text"));
1868
1869 let value = serde_json::to_value(data).unwrap();
1870 assert_eq!(value, serde_json::json!("some text"));
1871
1872 let data = SearchQueryMatchData::Bytes(vec![1, 2, 3]);
1874
1875 let value = serde_json::to_value(data).unwrap();
1876 assert_eq!(value, serde_json::json!([1, 2, 3]));
1877 }
1878
1879 #[test]
1880 fn should_be_able_to_deserialize_from_json() {
1881 let value = serde_json::json!("some text");
1882
1883 let data: SearchQueryMatchData = serde_json::from_value(value).unwrap();
1884 assert_eq!(data, SearchQueryMatchData::Text(String::from("some text")));
1885
1886 let value = serde_json::json!([1, 2, 3]);
1888
1889 let data: SearchQueryMatchData = serde_json::from_value(value).unwrap();
1890 assert_eq!(data, SearchQueryMatchData::Bytes(vec![1, 2, 3]));
1891 }
1892
1893 #[test]
1894 fn should_be_able_to_serialize_to_msgpack() {
1895 let data = SearchQueryMatchData::Text(String::from("some text"));
1896
1897 let _ = rmp_serde::encode::to_vec_named(&data).unwrap();
1902
1903 let data = SearchQueryMatchData::Bytes(vec![1, 2, 3]);
1905 let _ = rmp_serde::encode::to_vec_named(&data).unwrap();
1906 }
1907
1908 #[test]
1909 fn should_be_able_to_deserialize_from_msgpack() {
1910 let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatchData::Text(String::from(
1915 "some text",
1916 )))
1917 .unwrap();
1918
1919 let data: SearchQueryMatchData = rmp_serde::decode::from_slice(&buf).unwrap();
1920 assert_eq!(data, SearchQueryMatchData::Text(String::from("some text")));
1921
1922 let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatchData::Bytes(vec![1, 2, 3]))
1924 .unwrap();
1925
1926 let data: SearchQueryMatchData = rmp_serde::decode::from_slice(&buf).unwrap();
1927 assert_eq!(data, SearchQueryMatchData::Bytes(vec![1, 2, 3]));
1928 }
1929 }
1930}