use std::borrow::Cow; use std::collections::HashSet; use std::path::PathBuf; use std::str::FromStr; use serde::{Deserialize, Serialize}; use crate::common::FileType; use crate::utils; /// Id associated with a search pub type SearchId = u32; /// Represents a query to perform against the filesystem #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SearchQuery { /// Kind of data to examine using condition pub target: SearchQueryTarget, /// Condition to meet to be considered a match pub condition: SearchQueryCondition, /// Paths in which to perform the query pub paths: Vec, /// Options to apply to the query #[serde(default)] pub options: SearchQueryOptions, } impl SearchQuery { /// Creates a search query targeting the contents of files. pub fn contents( condition: SearchQueryCondition, paths: I, options: SearchQueryOptions, ) -> Self where I: IntoIterator, T: Into, { Self { target: SearchQueryTarget::Contents, condition, paths: paths.into_iter().map(Into::into).collect(), options, } } /// Creates a search query targeting the paths of files, directories, and symlinks. pub fn path( condition: SearchQueryCondition, paths: I, options: SearchQueryOptions, ) -> Self where I: IntoIterator, T: Into, { Self { target: SearchQueryTarget::Path, condition, paths: paths.into_iter().map(Into::into).collect(), options, } } } /// Kind of data to examine using conditions #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum SearchQueryTarget { /// Checks path of file, directory, or symlink Path, /// Checks contents of files Contents, } /// Condition used to find a match in a search query #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case", deny_unknown_fields, tag = "type")] pub enum SearchQueryCondition { /// Text is found anywhere (all regex patterns are escaped) Contains { value: String }, /// Begins with some text (all regex patterns are escaped) EndsWith { value: String }, /// Matches some text exactly (all regex patterns are escaped) Equals { value: String }, /// Any of the conditions match Or { value: Vec }, /// Matches some regex Regex { value: String }, /// Begins with some text (all regex patterns are escaped) StartsWith { value: String }, } impl SearchQueryCondition { /// Creates a new instance with `Contains` variant pub fn contains(value: impl Into) -> Self { Self::Contains { value: value.into(), } } /// Creates a new instance with `EndsWith` variant pub fn ends_with(value: impl Into) -> Self { Self::EndsWith { value: value.into(), } } /// Creates a new instance with `Equals` variant pub fn equals(value: impl Into) -> Self { Self::Equals { value: value.into(), } } /// Creates a new instance with `Or` variant pub fn or(value: I) -> Self where I: IntoIterator, C: Into, { Self::Or { value: value.into_iter().map(|s| s.into()).collect(), } } /// Creates a new instance with `Regex` variant pub fn regex(value: impl Into) -> Self { Self::Regex { value: value.into(), } } /// Creates a new instance with `StartsWith` variant pub fn starts_with(value: impl Into) -> Self { Self::StartsWith { value: value.into(), } } /// Converts the condition in a regex string pub fn to_regex_string(&self) -> String { match self { Self::Contains { value } => regex::escape(value), Self::EndsWith { value } => format!(r"{}$", regex::escape(value)), Self::Equals { value } => format!(r"^{}$", regex::escape(value)), Self::Regex { value } => value.to_string(), Self::StartsWith { value } => format!(r"^{}", regex::escape(value)), Self::Or { value } => { let mut s = String::new(); for (i, condition) in value.iter().enumerate() { if i > 0 { s.push('|'); } s.push_str(&condition.to_regex_string()); } s } } } } impl FromStr for SearchQueryCondition { type Err = std::convert::Infallible; /// Parses search query from a JSON string fn from_str(s: &str) -> Result { Ok(Self::regex(s)) } } /// Options associated with a search query #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(default)] pub struct SearchQueryOptions { /// Restrict search to only these file types (otherwise all are allowed). #[serde(skip_serializing_if = "HashSet::is_empty")] pub allowed_file_types: HashSet, /// Regex to use to filter paths being searched to only those that match the include condition. #[serde(skip_serializing_if = "Option::is_none")] pub include: Option, /// Regex to use to filter paths being searched to only those that do not match the exclude. /// condition #[serde(skip_serializing_if = "Option::is_none")] pub exclude: Option, /// If true, will search upward through parent directories rather than the traditional downward /// search that recurses through all children directories. /// /// Note that this will use maximum depth to apply to the reverse direction, and will only look /// through each ancestor directory's immediate entries. In other words, this will not result /// in recursing through sibling directories. /// /// An upward search will ALWAYS search the contents of a directory, so this means providing a /// path to a directory will search its entries EVEN if the max_depth is 0. #[serde(skip_serializing_if = "utils::is_false")] pub upward: bool, /// Search should follow symbolic links. #[serde(skip_serializing_if = "utils::is_false")] pub follow_symbolic_links: bool, /// Maximum results to return before stopping the query. #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option, /// Maximum depth (directories) to search /// /// The smallest depth is 0 and always corresponds to the path given to the new function on /// this type. Its direct descendents have depth 1, and their descendents have depth 2, and so /// on. /// /// Note that this will not simply filter the entries of the iterator, but it will actually /// avoid descending into directories when the depth is exceeded. #[serde(skip_serializing_if = "Option::is_none")] pub max_depth: Option, /// Amount of results to batch before sending back excluding final submission that will always /// include the remaining results even if less than pagination request. #[serde(skip_serializing_if = "Option::is_none")] pub pagination: Option, /// If true, will skip searching hidden files. #[serde(skip_serializing_if = "utils::is_false")] pub ignore_hidden: bool, /// If true, will read `.ignore` files that are used by `ripgrep` and `The Silver Searcher` /// to determine which files and directories to not search. #[serde(skip_serializing_if = "utils::is_false")] pub use_ignore_files: bool, /// If true, will read `.ignore` files from parent directories that are used by `ripgrep` and /// `The Silver Searcher` to determine which files and directories to not search. #[serde(skip_serializing_if = "utils::is_false")] pub use_parent_ignore_files: bool, /// If true, will read `.gitignore` files to determine which files and directories to not /// search. #[serde(skip_serializing_if = "utils::is_false")] pub use_git_ignore_files: bool, /// If true, will read global `.gitignore` files to determine which files and directories to /// not search. #[serde(skip_serializing_if = "utils::is_false")] pub use_global_git_ignore_files: bool, /// If true, will read `.git/info/exclude` files to determine which files and directories to /// not search. #[serde(skip_serializing_if = "utils::is_false")] pub use_git_exclude_files: bool, } /// Represents a match for a search query #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case", deny_unknown_fields, tag = "type")] pub enum SearchQueryMatch { /// Matches part of a file's path Path(SearchQueryPathMatch), /// Matches part of a file's contents Contents(SearchQueryContentsMatch), } impl SearchQueryMatch { pub fn into_path_match(self) -> Option { match self { Self::Path(x) => Some(x), _ => None, } } pub fn into_contents_match(self) -> Option { match self { Self::Contents(x) => Some(x), _ => None, } } } /// Represents details for a match on a path #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SearchQueryPathMatch { /// Path associated with the match pub path: PathBuf, /// Collection of matches tied to `path` where each submatch's byte offset is relative to /// `path` pub submatches: Vec, } /// Represents details for a match on a file's contents #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SearchQueryContentsMatch { /// Path to file whose contents match pub path: PathBuf, /// Line(s) that matched pub lines: SearchQueryMatchData, /// Line number where match starts (base index 1) pub line_number: u64, /// Absolute byte offset corresponding to the start of `lines` in the data being searched pub absolute_offset: u64, /// Collection of matches tied to `lines` where each submatch's byte offset is relative to /// `lines` and not the overall content pub submatches: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SearchQuerySubmatch { /// Content matched by query pub r#match: SearchQueryMatchData, /// Byte offset representing start of submatch (inclusive) pub start: u64, /// Byte offset representing end of submatch (exclusive) pub end: u64, } impl SearchQuerySubmatch { /// Creates a new submatch using the given `match` data, `start`, and `end`. pub fn new(r#match: impl Into, start: u64, end: u64) -> Self { Self { r#match: r#match.into(), start, end, } } } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(untagged)] pub enum SearchQueryMatchData { /// Match represented as bytes Bytes(Vec), /// Match represented as UTF-8 text Text(String), } impl SearchQueryMatchData { /// Creates a new instance with `Text` variant pub fn text(value: impl Into) -> Self { Self::Text(value.into()) } /// Creates a new instance with `Bytes` variant pub fn bytes(value: impl Into>) -> Self { Self::Bytes(value.into()) } /// Returns the UTF-8 str reference to the data, if is valid UTF-8 pub fn to_str(&self) -> Option<&str> { match self { Self::Text(x) => Some(x), Self::Bytes(x) => std::str::from_utf8(x).ok(), } } /// Converts data to a UTF-8 string, replacing any invalid UTF-8 sequences with /// [`U+FFFD REPLACEMENT CHARACTER`](https://doc.rust-lang.org/nightly/core/char/const.REPLACEMENT_CHARACTER.html) pub fn to_string_lossy(&self) -> Cow<'_, str> { match self { Self::Text(x) => Cow::Borrowed(x), Self::Bytes(x) => String::from_utf8_lossy(x), } } } impl From> for SearchQueryMatchData { fn from(bytes: Vec) -> Self { Self::Bytes(bytes) } } impl<'a> From<&'a [u8]> for SearchQueryMatchData { fn from(bytes: &'a [u8]) -> Self { Self::Bytes(bytes.to_vec()) } } impl From for SearchQueryMatchData { fn from(text: String) -> Self { Self::Text(text) } } impl<'a> From<&'a str> for SearchQueryMatchData { fn from(text: &'a str) -> Self { Self::Text(text.to_string()) } } #[cfg(test)] mod tests { use super::*; mod search_query { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let query = SearchQuery { target: SearchQueryTarget::Contents, condition: SearchQueryCondition::equals("hello world"), paths: vec![PathBuf::from("path1"), PathBuf::from("path2")], options: SearchQueryOptions::default(), }; let value = serde_json::to_value(query).unwrap(); assert_eq!( value, serde_json::json!({ "target": "contents", "condition": { "type": "equals", "value": "hello world", }, "paths": ["path1", "path2"], "options": {}, }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "target": "contents", "condition": { "type": "equals", "value": "hello world", }, "paths": ["path1", "path2"], }); let query: SearchQuery = serde_json::from_value(value).unwrap(); assert_eq!( query, SearchQuery { target: SearchQueryTarget::Contents, condition: SearchQueryCondition::equals("hello world"), paths: vec![PathBuf::from("path1"), PathBuf::from("path2")], options: SearchQueryOptions::default(), } ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let query = SearchQuery { target: SearchQueryTarget::Contents, condition: SearchQueryCondition::equals("hello world"), paths: vec![PathBuf::from("path1"), PathBuf::from("path2")], options: SearchQueryOptions::default(), }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&query).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQuery { target: SearchQueryTarget::Contents, condition: SearchQueryCondition::equals("hello world"), paths: vec![PathBuf::from("path1"), PathBuf::from("path2")], options: SearchQueryOptions::default(), }) .unwrap(); let query: SearchQuery = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( query, SearchQuery { target: SearchQueryTarget::Contents, condition: SearchQueryCondition::equals("hello world"), paths: vec![PathBuf::from("path1"), PathBuf::from("path2")], options: SearchQueryOptions::default(), } ); } } mod search_query_target { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let target = SearchQueryTarget::Contents; let value = serde_json::to_value(target).unwrap(); assert_eq!(value, serde_json::json!("contents")); let target = SearchQueryTarget::Path; let value = serde_json::to_value(target).unwrap(); assert_eq!(value, serde_json::json!("path")); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!("contents"); let target: SearchQueryTarget = serde_json::from_value(value).unwrap(); assert_eq!(target, SearchQueryTarget::Contents); let value = serde_json::json!("path"); let target: SearchQueryTarget = serde_json::from_value(value).unwrap(); assert_eq!(target, SearchQueryTarget::Path); } #[test] fn should_be_able_to_serialize_to_msgpack() { // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let target = SearchQueryTarget::Contents; let _ = rmp_serde::encode::to_vec_named(&target).unwrap(); let target = SearchQueryTarget::Path; let _ = rmp_serde::encode::to_vec_named(&target).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryTarget::Contents).unwrap(); let target: SearchQueryTarget = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(target, SearchQueryTarget::Contents); let buf = rmp_serde::encode::to_vec_named(&SearchQueryTarget::Path).unwrap(); let target: SearchQueryTarget = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(target, SearchQueryTarget::Path); } } mod search_query_condition { use super::*; #[test] fn to_regex_string_should_convert_to_appropriate_regex_and_escape_as_needed() { assert_eq!( SearchQueryCondition::contains("t^es$t").to_regex_string(), r"t\^es\$t" ); assert_eq!( SearchQueryCondition::ends_with("t^es$t").to_regex_string(), r"t\^es\$t$" ); assert_eq!( SearchQueryCondition::equals("t^es$t").to_regex_string(), r"^t\^es\$t$" ); assert_eq!( SearchQueryCondition::or([ SearchQueryCondition::contains("t^es$t"), SearchQueryCondition::equals("t^es$t"), SearchQueryCondition::regex("^test$"), ]) .to_regex_string(), r"t\^es\$t|^t\^es\$t$|^test$" ); assert_eq!( SearchQueryCondition::regex("test").to_regex_string(), "test" ); assert_eq!( SearchQueryCondition::starts_with("t^es$t").to_regex_string(), r"^t\^es\$t" ); } mod contains { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::contains("some text"); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "contains", "value": "some text", }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "contains", "value": "some text", }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!(condition, SearchQueryCondition::contains("some text")); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::contains("some text"); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::contains("some text")) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(condition, SearchQueryCondition::contains("some text")); } } mod ends_with { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::ends_with("some text"); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "ends_with", "value": "some text", }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "ends_with", "value": "some text", }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!(condition, SearchQueryCondition::ends_with("some text")); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::ends_with("some text"); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::ends_with("some text")) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(condition, SearchQueryCondition::ends_with("some text")); } } mod equals { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::equals("some text"); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "equals", "value": "some text", }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "equals", "value": "some text", }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!(condition, SearchQueryCondition::equals("some text")); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::equals("some text"); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::equals("some text")) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(condition, SearchQueryCondition::equals("some text")); } } mod or { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::or([ SearchQueryCondition::starts_with("start text"), SearchQueryCondition::ends_with("end text"), ]); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "or", "value": [ { "type": "starts_with", "value": "start text" }, { "type": "ends_with", "value": "end text" }, ], }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "or", "value": [ { "type": "starts_with", "value": "start text" }, { "type": "ends_with", "value": "end text" }, ], }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!( condition, SearchQueryCondition::or([ SearchQueryCondition::starts_with("start text"), SearchQueryCondition::ends_with("end text"), ]) ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::or([ SearchQueryCondition::starts_with("start text"), SearchQueryCondition::ends_with("end text"), ]); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::or([ SearchQueryCondition::starts_with("start text"), SearchQueryCondition::ends_with("end text"), ])) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( condition, SearchQueryCondition::or([ SearchQueryCondition::starts_with("start text"), SearchQueryCondition::ends_with("end text"), ]) ); } } mod regex { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::regex("some text"); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "regex", "value": "some text", }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "regex", "value": "some text", }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!(condition, SearchQueryCondition::regex("some text")); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::regex("some text"); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::regex("some text")) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(condition, SearchQueryCondition::regex("some text")); } } mod starts_with { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let condition = SearchQueryCondition::starts_with("some text"); let value = serde_json::to_value(condition).unwrap(); assert_eq!( value, serde_json::json!({ "type": "starts_with", "value": "some text", }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "starts_with", "value": "some text", }); let condition: SearchQueryCondition = serde_json::from_value(value).unwrap(); assert_eq!(condition, SearchQueryCondition::starts_with("some text")); } #[test] fn should_be_able_to_serialize_to_msgpack() { let condition = SearchQueryCondition::starts_with("some text"); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&condition).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryCondition::starts_with( "some text", )) .unwrap(); let condition: SearchQueryCondition = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(condition, SearchQueryCondition::starts_with("some text")); } } } mod search_query_options { use super::*; #[test] fn should_be_able_to_serialize_minimal_options_to_json() { let options = SearchQueryOptions { allowed_file_types: [].into_iter().collect(), include: None, exclude: None, upward: false, follow_symbolic_links: false, limit: None, max_depth: None, pagination: None, ignore_hidden: false, use_ignore_files: false, use_parent_ignore_files: false, use_git_ignore_files: false, use_global_git_ignore_files: false, use_git_exclude_files: false, }; let value = serde_json::to_value(options).unwrap(); assert_eq!(value, serde_json::json!({})); } #[test] fn should_be_able_to_serialize_full_options_to_json() { let options = SearchQueryOptions { allowed_file_types: [FileType::File].into_iter().collect(), include: Some(SearchQueryCondition::Equals { value: String::from("hello"), }), exclude: Some(SearchQueryCondition::Contains { value: String::from("world"), }), upward: true, follow_symbolic_links: true, limit: Some(u64::MAX), max_depth: Some(u64::MAX), pagination: Some(u64::MAX), ignore_hidden: true, use_ignore_files: true, use_parent_ignore_files: true, use_git_ignore_files: true, use_global_git_ignore_files: true, use_git_exclude_files: true, }; let value = serde_json::to_value(options).unwrap(); assert_eq!( value, serde_json::json!({ "allowed_file_types": ["file"], "include": { "type": "equals", "value": "hello", }, "exclude": { "type": "contains", "value": "world", }, "upward": true, "follow_symbolic_links": true, "limit": u64::MAX, "max_depth": u64::MAX, "pagination": u64::MAX, "ignore_hidden": true, "use_ignore_files": true, "use_parent_ignore_files": true, "use_git_ignore_files": true, "use_global_git_ignore_files": true, "use_git_exclude_files": true, }) ); } #[test] fn should_be_able_to_deserialize_minimal_options_from_json() { let value = serde_json::json!({}); let options: SearchQueryOptions = serde_json::from_value(value).unwrap(); assert_eq!( options, SearchQueryOptions { allowed_file_types: [].into_iter().collect(), include: None, exclude: None, upward: false, follow_symbolic_links: false, limit: None, max_depth: None, pagination: None, ignore_hidden: false, use_ignore_files: false, use_parent_ignore_files: false, use_git_ignore_files: false, use_global_git_ignore_files: false, use_git_exclude_files: false, } ); } #[test] fn should_be_able_to_deserialize_full_options_from_json() { let value = serde_json::json!({ "allowed_file_types": ["file"], "include": { "type": "equals", "value": "hello", }, "exclude": { "type": "contains", "value": "world", }, "upward": true, "follow_symbolic_links": true, "limit": u64::MAX, "max_depth": u64::MAX, "pagination": u64::MAX, "ignore_hidden": true, "use_ignore_files": true, "use_parent_ignore_files": true, "use_git_ignore_files": true, "use_global_git_ignore_files": true, "use_git_exclude_files": true, }); let options: SearchQueryOptions = serde_json::from_value(value).unwrap(); assert_eq!( options, SearchQueryOptions { allowed_file_types: [FileType::File].into_iter().collect(), include: Some(SearchQueryCondition::Equals { value: String::from("hello"), }), exclude: Some(SearchQueryCondition::Contains { value: String::from("world"), }), upward: true, follow_symbolic_links: true, limit: Some(u64::MAX), max_depth: Some(u64::MAX), pagination: Some(u64::MAX), ignore_hidden: true, use_ignore_files: true, use_parent_ignore_files: true, use_git_ignore_files: true, use_global_git_ignore_files: true, use_git_exclude_files: true, } ); } #[test] fn should_be_able_to_serialize_minimal_options_to_msgpack() { let options = SearchQueryOptions { allowed_file_types: [].into_iter().collect(), include: None, exclude: None, upward: false, follow_symbolic_links: false, limit: None, max_depth: None, pagination: None, ignore_hidden: false, use_ignore_files: false, use_parent_ignore_files: false, use_git_ignore_files: false, use_global_git_ignore_files: false, use_git_exclude_files: false, }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&options).unwrap(); } #[test] fn should_be_able_to_serialize_full_options_to_msgpack() { let options = SearchQueryOptions { allowed_file_types: [FileType::File].into_iter().collect(), include: Some(SearchQueryCondition::Equals { value: String::from("hello"), }), exclude: Some(SearchQueryCondition::Contains { value: String::from("world"), }), upward: true, follow_symbolic_links: true, limit: Some(u64::MAX), max_depth: Some(u64::MAX), pagination: Some(u64::MAX), ignore_hidden: true, use_ignore_files: true, use_parent_ignore_files: true, use_git_ignore_files: true, use_global_git_ignore_files: true, use_git_exclude_files: true, }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&options).unwrap(); } #[test] fn should_be_able_to_deserialize_minimal_options_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryOptions { allowed_file_types: [].into_iter().collect(), include: None, exclude: None, upward: false, follow_symbolic_links: false, limit: None, max_depth: None, pagination: None, ignore_hidden: false, use_ignore_files: false, use_parent_ignore_files: false, use_git_ignore_files: false, use_global_git_ignore_files: false, use_git_exclude_files: false, }) .unwrap(); let options: SearchQueryOptions = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( options, SearchQueryOptions { allowed_file_types: [].into_iter().collect(), include: None, exclude: None, upward: false, follow_symbolic_links: false, limit: None, max_depth: None, pagination: None, ignore_hidden: false, use_ignore_files: false, use_parent_ignore_files: false, use_git_ignore_files: false, use_global_git_ignore_files: false, use_git_exclude_files: false, } ); } #[test] fn should_be_able_to_deserialize_full_options_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryOptions { allowed_file_types: [FileType::File].into_iter().collect(), include: Some(SearchQueryCondition::Equals { value: String::from("hello"), }), exclude: Some(SearchQueryCondition::Contains { value: String::from("world"), }), upward: true, follow_symbolic_links: true, limit: Some(u64::MAX), max_depth: Some(u64::MAX), pagination: Some(u64::MAX), ignore_hidden: true, use_ignore_files: true, use_parent_ignore_files: true, use_git_ignore_files: true, use_global_git_ignore_files: true, use_git_exclude_files: true, }) .unwrap(); let options: SearchQueryOptions = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( options, SearchQueryOptions { allowed_file_types: [FileType::File].into_iter().collect(), include: Some(SearchQueryCondition::Equals { value: String::from("hello"), }), exclude: Some(SearchQueryCondition::Contains { value: String::from("world"), }), upward: true, follow_symbolic_links: true, limit: Some(u64::MAX), max_depth: Some(u64::MAX), pagination: Some(u64::MAX), ignore_hidden: true, use_ignore_files: true, use_parent_ignore_files: true, use_git_ignore_files: true, use_global_git_ignore_files: true, use_git_exclude_files: true, } ); } } mod search_query_match { use super::*; mod for_path { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let r#match = SearchQueryMatch::Path(SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }); let value = serde_json::to_value(r#match).unwrap(); assert_eq!( value, serde_json::json!({ "type": "path", "path": "path", "submatches": [{ "match": "text", "start": 8, "end": 13, }], }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "path", "path": "path", "submatches": [{ "match": "text", "start": 8, "end": 13, }], }); let r#match: SearchQueryMatch = serde_json::from_value(value).unwrap(); assert_eq!( r#match, SearchQueryMatch::Path(SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let r#match = SearchQueryMatch::Path(SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatch::Path( SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }, )) .unwrap(); let r#match: SearchQueryMatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( r#match, SearchQueryMatch::Path(SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) ); } } mod for_contents { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let r#match = SearchQueryMatch::Contents(SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }); let value = serde_json::to_value(r#match).unwrap(); assert_eq!( value, serde_json::json!({ "type": "contents", "path": "path", "lines": "some text", "line_number": 12, "absolute_offset": 24, "submatches": [{ "match": "text", "start": 8, "end": 13, }], }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "type": "contents", "path": "path", "lines": "some text", "line_number": 12, "absolute_offset": 24, "submatches": [{ "match": "text", "start": 8, "end": 13, }], }); let r#match: SearchQueryMatch = serde_json::from_value(value).unwrap(); assert_eq!( r#match, SearchQueryMatch::Contents(SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let r#match = SearchQueryMatch::Contents(SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatch::Contents( SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }, )) .unwrap(); let r#match: SearchQueryMatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( r#match, SearchQueryMatch::Contents(SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) ); } } } mod search_query_path_match { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let r#match = SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }; let value = serde_json::to_value(r#match).unwrap(); assert_eq!( value, serde_json::json!({ "path": "path", "submatches": [{ "match": "text", "start": 8, "end": 13, }], }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "path": "path", "submatches": [{ "match": "text", "start": 8, "end": 13, }], }); let r#match: SearchQueryPathMatch = serde_json::from_value(value).unwrap(); assert_eq!( r#match, SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], } ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let r#match = SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) .unwrap(); let r#match: SearchQueryPathMatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( r#match, SearchQueryPathMatch { path: PathBuf::from("path"), submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], } ); } } mod search_query_contents_match { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let r#match = SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }; let value = serde_json::to_value(r#match).unwrap(); assert_eq!( value, serde_json::json!({ "path": "path", "lines": "some text", "line_number": 12, "absolute_offset": 24, "submatches": [{ "match": "text", "start": 8, "end": 13, }], }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "path": "path", "lines": "some text", "line_number": 12, "absolute_offset": 24, "submatches": [{ "match": "text", "start": 8, "end": 13, }], }); let r#match: SearchQueryContentsMatch = serde_json::from_value(value).unwrap(); assert_eq!( r#match, SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], } ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let r#match = SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&r#match).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], }) .unwrap(); let r#match: SearchQueryContentsMatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( r#match, SearchQueryContentsMatch { path: PathBuf::from("path"), lines: SearchQueryMatchData::Text(String::from("some text")), line_number: 12, absolute_offset: 24, submatches: vec![SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("text")), start: 8, end: 13, }], } ); } } mod search_query_submatch { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let data = SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("some text")), start: 12, end: 24, }; let value = serde_json::to_value(data).unwrap(); assert_eq!( value, serde_json::json!({ "match": "some text", "start": 12, "end": 24, }) ); let data = SearchQuerySubmatch { r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]), start: 12, end: 24, }; // Do the same for bytes let value = serde_json::to_value(data).unwrap(); assert_eq!( value, serde_json::json!({ "match": [1, 2, 3], "start": 12, "end": 24, }) ); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!({ "match": "some text", "start": 12, "end": 24, }); let submatch: SearchQuerySubmatch = serde_json::from_value(value).unwrap(); assert_eq!( submatch, SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("some text")), start: 12, end: 24, } ); // Do the same for bytes let value = serde_json::json!({ "match": [1, 2, 3], "start": 12, "end": 24, }); let submatch: SearchQuerySubmatch = serde_json::from_value(value).unwrap(); assert_eq!( submatch, SearchQuerySubmatch { r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]), start: 12, end: 24, } ); } #[test] fn should_be_able_to_serialize_to_msgpack() { let submatch = SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("some text")), start: 12, end: 24, }; // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&submatch).unwrap(); // Do the same for bytes let submatch = SearchQuerySubmatch { r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]), start: 12, end: 24, }; let _ = rmp_serde::encode::to_vec_named(&submatch).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("some text")), start: 12, end: 24, }) .unwrap(); let submatch: SearchQuerySubmatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( submatch, SearchQuerySubmatch { r#match: SearchQueryMatchData::Text(String::from("some text")), start: 12, end: 24, } ); // Do the same for bytes let buf = rmp_serde::encode::to_vec_named(&SearchQuerySubmatch { r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]), start: 12, end: 24, }) .unwrap(); let submatch: SearchQuerySubmatch = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!( submatch, SearchQuerySubmatch { r#match: SearchQueryMatchData::Bytes(vec![1, 2, 3]), start: 12, end: 24, } ); } } mod search_query_match_data { use super::*; #[test] fn should_be_able_to_serialize_to_json() { let data = SearchQueryMatchData::Text(String::from("some text")); let value = serde_json::to_value(data).unwrap(); assert_eq!(value, serde_json::json!("some text")); // Do the same for bytes let data = SearchQueryMatchData::Bytes(vec![1, 2, 3]); let value = serde_json::to_value(data).unwrap(); assert_eq!(value, serde_json::json!([1, 2, 3])); } #[test] fn should_be_able_to_deserialize_from_json() { let value = serde_json::json!("some text"); let data: SearchQueryMatchData = serde_json::from_value(value).unwrap(); assert_eq!(data, SearchQueryMatchData::Text(String::from("some text"))); // Do the same for bytes let value = serde_json::json!([1, 2, 3]); let data: SearchQueryMatchData = serde_json::from_value(value).unwrap(); assert_eq!(data, SearchQueryMatchData::Bytes(vec![1, 2, 3])); } #[test] fn should_be_able_to_serialize_to_msgpack() { let data = SearchQueryMatchData::Text(String::from("some text")); // NOTE: We don't actually check the output here because it's an implementation detail // and could change as we change how serialization is done. This is merely to verify // that we can serialize since there are times when serde fails to serialize at // runtime. let _ = rmp_serde::encode::to_vec_named(&data).unwrap(); // Do the same for bytes let data = SearchQueryMatchData::Bytes(vec![1, 2, 3]); let _ = rmp_serde::encode::to_vec_named(&data).unwrap(); } #[test] fn should_be_able_to_deserialize_from_msgpack() { // NOTE: It may seem odd that we are serializing just to deserialize, but this is to // verify that we are not corrupting or causing issues when serializing on a // client/server and then trying to deserialize on the other side. This has happened // enough times with minor changes that we need tests to verify. let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatchData::Text(String::from( "some text", ))) .unwrap(); let data: SearchQueryMatchData = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(data, SearchQueryMatchData::Text(String::from("some text"))); // Do the same for bytes let buf = rmp_serde::encode::to_vec_named(&SearchQueryMatchData::Bytes(vec![1, 2, 3])) .unwrap(); let data: SearchQueryMatchData = rmp_serde::decode::from_slice(&buf).unwrap(); assert_eq!(data, SearchQueryMatchData::Bytes(vec![1, 2, 3])); } } }