From 47d0bd68edfb220e77b9e7bfde0ce52866115edd Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 29 Apr 2021 09:12:00 -0700 Subject: [PATCH 1/5] move wql to a separate crate Signed-off-by: Andrew Whitehead --- Cargo.toml | 7 +- indy-wql/Cargo.toml | 28 + indy-wql/src/lib.rs | 2972 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 3006 insertions(+), 1 deletion(-) create mode 100644 indy-wql/Cargo.toml create mode 100644 indy-wql/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index abfd68d..f5d1ec7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,10 @@ members = [ "indy-credx", "indy-data-types", "indy-test-utils", - "indy-utils" + "indy-utils", + "indy-wql" ] + +[profile.release] +lto = true +codegen-units = 1 diff --git a/indy-wql/Cargo.toml b/indy-wql/Cargo.toml new file mode 100644 index 0000000..aec381e --- /dev/null +++ b/indy-wql/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "indy-wql" +version = "0.4.0" +authors = ["Hyperledger Indy Contributors "] +description = "Utilities for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." +edition = "2018" +license = "Apache-2.0" +readme = "../README.md" +repository = "https://github.com/hyperledger/indy-shared-rs/" +categories = ["authentication", "cryptography"] +keywords = ["hyperledger", "indy", "ssi", "verifiable", "credentials"] + +[lib] +name = "indy_wql" +path = "src/lib.rs" +crate-type = ["rlib"] + +[features] +default = ["serde_support"] +serde_support = ["serde", "serde_json"] + +[dependencies] +serde = { version = "1.0", optional = true, default-features = false } +serde_json = { version = "1.0", optional = true, default-features = false } + +[dev-dependencies] +rand = "0.8" +serde_json = "1.0" diff --git a/indy-wql/src/lib.rs b/indy-wql/src/lib.rs new file mode 100644 index 0000000..869b0bc --- /dev/null +++ b/indy-wql/src/lib.rs @@ -0,0 +1,2972 @@ +//! Indy WQL (wallet query language) parsing and optimization + +#![deny(missing_debug_implementations, missing_docs, rust_2018_idioms)] + +/// An abstract query representation over a key and value type +#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum AbstractQuery { + /// Logical AND of multiple clauses + And(Vec), + /// Logical OR of multiple clauses + Or(Vec), + /// Negation of a clause + Not(Box), + /// Equality comparison for a field value + Eq(K, V), + /// Inequality comparison for a field value + Neq(K, V), + /// Greater-than comparison for a field value + Gt(K, V), + /// Greater-than-or-equal comparison for a field value + Gte(K, V), + /// Less-than comparison for a field value + Lt(K, V), + /// Less-than-or-equal comparison for a field value + Lte(K, V), + /// SQL 'LIKE'-compatible string comparison for a field value + Like(K, V), + /// Match one of multiple field values in a set + In(K, Vec), + /// Match any non-null field value of the given field names + Exist(Vec), +} + +/// A concrete query implementation with String keys and values +pub type Query = AbstractQuery; + +impl AbstractQuery { + /// Perform basic query clause optimization + pub fn optimise(self) -> Option { + match self { + Self::Not(boxed_query) => match boxed_query.optimise() { + None => None, + Some(Self::Not(nested_query)) => Some(*nested_query), + Some(other) => Some(Self::Not(Box::new(other))), + }, + Self::And(subqueries) => { + let mut subqueries: Vec = subqueries + .into_iter() + .flat_map(|query| query.optimise()) + .collect(); + + match subqueries.len() { + 0 => None, + 1 => Some(subqueries.remove(0)), + _ => Some(Self::And(subqueries)), + } + } + Self::Or(subqueries) => { + let mut subqueries: Vec = subqueries + .into_iter() + .flat_map(|query| query.optimise()) + .collect(); + + match subqueries.len() { + 0 => None, + 1 => Some(subqueries.remove(0)), + _ => Some(Self::Or(subqueries)), + } + } + Self::In(key, mut targets) if targets.len() == 1 => { + Some(Self::Eq(key, targets.remove(0))) + } + other => Some(other), + } + } + + /// Perform a transformation on all field names in query clauses + pub fn map_names( + self, + mut f: impl FnMut(K) -> Result, + ) -> Result, E> { + self.map(&mut f, &mut |_k, v| Ok(v)) + } + + /// Perform a transformation on all field values in query clauses + pub fn map_values( + self, + mut f: impl FnMut(&K, V) -> Result, + ) -> Result, E> { + self.map(&mut |k| Ok(k), &mut f) + } + + /// Transform all query clauses using field name and value conversions + pub fn map( + self, + kf: &mut KF, + vf: &mut VF, + ) -> Result, E> + where + KF: FnMut(K) -> Result, + VF: FnMut(&K, V) -> Result, + { + match self { + Self::Eq(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Eq(kf(tag_name)?, tag_value)) + } + Self::Neq(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Neq(kf(tag_name)?, tag_value)) + } + Self::Gt(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Gt(kf(tag_name)?, tag_value)) + } + Self::Gte(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Gte(kf(tag_name)?, tag_value)) + } + Self::Lt(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Lt(kf(tag_name)?, tag_value)) + } + Self::Lte(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Lte(kf(tag_name)?, tag_value)) + } + Self::Like(tag_name, tag_value) => { + let tag_value = vf(&tag_name, tag_value)?; + Ok(AbstractQuery::::Like(kf(tag_name)?, tag_value)) + } + Self::In(tag_name, tag_values) => { + let tag_values = tag_values + .into_iter() + .map(|value| vf(&tag_name, value)) + .collect::, E>>()?; + Ok(AbstractQuery::::In(kf(tag_name)?, tag_values)) + } + Self::Exist(tag_names) => Ok(AbstractQuery::::Exist( + tag_names.into_iter().try_fold(vec![], |mut v, tag_name| { + v.push(kf(tag_name)?); + Result::<_, E>::Ok(v) + })?, + )), + Self::And(subqueries) => { + let subqueries = subqueries + .into_iter() + .map(|query| query.map(kf, vf)) + .collect::, E>>()?; + Ok(AbstractQuery::::And(subqueries)) + } + Self::Or(subqueries) => { + let subqueries = subqueries + .into_iter() + .map(|query| query.map(kf, vf)) + .collect::, E>>()?; + Ok(AbstractQuery::::Or(subqueries)) + } + Self::Not(boxed_query) => Ok(AbstractQuery::::Not(Box::new( + boxed_query.map(kf, vf)?, + ))), + } + } +} + +impl Default for AbstractQuery { + fn default() -> Self { + Self::And(Vec::new()) + } +} + +#[cfg(feature = "serde_support")] +mod serde_support { + use std::string; + + use serde::ser::{Serialize, Serializer}; + use serde::{de, Deserialize, Deserializer}; + use serde_json::{self, json, Value as JsonValue}; + + use super::{AbstractQuery, Query}; + + impl Serialize for AbstractQuery + where + for<'a> &'a K: Into, + V: Serialize, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.to_value().serialize(serializer) + } + } + + impl<'de> Deserialize<'de> for Query { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let v = JsonValue::deserialize(deserializer)?; + + match v { + JsonValue::Object(map) => { + parse_query(map).map_err(|err| de::Error::missing_field(err)) + } + JsonValue::Array(array) => { + // cast old restrictions format to wql + let mut res: Vec = Vec::new(); + for sub_query in array { + let sub_query: serde_json::Map = sub_query + .as_object() + .ok_or_else(|| de::Error::custom("Restriction is invalid"))? + .clone() + .into_iter() + .filter(|&(_, ref v)| !v.is_null()) + .collect(); + + if !sub_query.is_empty() { + res.push(JsonValue::Object(sub_query)); + } + } + + let mut map = serde_json::Map::new(); + map.insert("$or".to_string(), JsonValue::Array(res)); + + parse_query(map).map_err(|err| de::Error::custom(err)) + } + _ => Err(de::Error::missing_field( + "Restriction must be either object or array", + )), + } + } + } + + impl AbstractQuery + where + for<'a> &'a K: Into, + V: Serialize, + { + fn to_value(&self) -> JsonValue { + match self { + Self::Eq(ref tag_name, ref tag_value) => json!({ tag_name: tag_value }), + Self::Neq(ref tag_name, ref tag_value) => json!({tag_name: {"$neq": tag_value}}), + Self::Gt(ref tag_name, ref tag_value) => json!({tag_name: {"$gt": tag_value}}), + Self::Gte(ref tag_name, ref tag_value) => json!({tag_name: {"$gte": tag_value}}), + Self::Lt(ref tag_name, ref tag_value) => json!({tag_name: {"$lt": tag_value}}), + Self::Lte(ref tag_name, ref tag_value) => json!({tag_name: {"$lte": tag_value}}), + Self::Like(ref tag_name, ref tag_value) => json!({tag_name: {"$like": tag_value}}), + Self::In(ref tag_name, ref tag_values) => json!({tag_name: {"$in":tag_values}}), + Self::Exist(ref tag_names) => { + json!({ "$exist": tag_names.iter().map(Into::into).collect::>() }) + } + Self::And(ref queries) => { + if !queries.is_empty() { + json!({ + "$and": queries.iter().map(|q| q.to_value()).collect::>() + }) + } else { + json!({}) + } + } + Self::Or(ref queries) => { + if !queries.is_empty() { + json!({ + "$or": queries.iter().map(|q| q.to_value()).collect::>() + }) + } else { + json!({}) + } + } + Self::Not(ref query) => json!({"$not": query.to_value()}), + } + } + } + + impl string::ToString for Query { + fn to_string(&self) -> String { + self.to_value().to_string() + } + } + + fn parse_query(map: serde_json::Map) -> Result { + let mut operators: Vec = Vec::new(); + + for (key, value) in map { + if let Some(operator_) = parse_operator(key, value)? { + operators.push(operator_); + } + } + + let query = if operators.len() == 1 { + operators.remove(0) + } else { + Query::And(operators) + }; + + Ok(query) + } + + fn parse_operator(key: String, value: JsonValue) -> Result, &'static str> { + match (key.as_str(), value) { + ("$and", JsonValue::Array(values)) => { + if values.is_empty() { + Ok(None) + } else { + let operators: Vec = parse_list_operators(values)?; + Ok(Some(Query::And(operators))) + } + } + ("$and", _) => Err("$and must be array of JSON objects"), + ("$or", JsonValue::Array(values)) => { + if values.is_empty() { + Ok(None) + } else { + let operators: Vec = parse_list_operators(values)?; + Ok(Some(Query::Or(operators))) + } + } + ("$or", _) => Err("$or must be array of JSON objects"), + ("$not", JsonValue::Object(map)) => { + let operator = parse_query(map)?; + Ok(Some(Query::Not(Box::new(operator)))) + } + ("$not", _) => Err("$not must be JSON object"), + ("$exist", JsonValue::String(key)) => Ok(Some(Query::Exist(vec![key]))), + ("$exist", JsonValue::Array(keys)) => { + if keys.is_empty() { + Ok(None) + } else { + let mut ks = vec![]; + for key in keys { + if let JsonValue::String(key) = key { + ks.push(key); + } else { + return Err("$exist must be used with a string or array of strings"); + } + } + Ok(Some(Query::Exist(ks))) + } + } + ("$exist", _) => Err("$exist must be used with a string or array of strings"), + (_, JsonValue::String(value)) => Ok(Some(Query::Eq(key, value))), + (_, JsonValue::Object(map)) => { + if map.len() == 1 { + let (operator_name, value) = map.into_iter().next().unwrap(); + parse_single_operator(operator_name, key, value).map(|operator| Some(operator)) + } else { + Err("value must be JSON object of length 1") + } + } + (_, _) => Err("Unsupported value"), + } + } + + fn parse_list_operators(operators: Vec) -> Result, &'static str> { + let mut out_operators: Vec = Vec::with_capacity(operators.len()); + + for value in operators.into_iter() { + if let JsonValue::Object(map) = value { + let subquery = parse_query(map)?; + out_operators.push(subquery); + } else { + return Err("operator must be array of JSON objects"); + } + } + + Ok(out_operators) + } + + fn parse_single_operator( + operator_name: String, + key: String, + value: JsonValue, + ) -> Result { + match (&*operator_name, value) { + ("$neq", JsonValue::String(value_)) => Ok(Query::Neq(key, value_)), + ("$neq", _) => Err("$neq must be used with string"), + ("$gt", JsonValue::String(value_)) => Ok(Query::Gt(key, value_)), + ("$gt", _) => Err("$gt must be used with string"), + ("$gte", JsonValue::String(value_)) => Ok(Query::Gte(key, value_)), + ("$gte", _) => Err("$gte must be used with string"), + ("$lt", JsonValue::String(value_)) => Ok(Query::Lt(key, value_)), + ("$lt", _) => Err("$lt must be used with string"), + ("$lte", JsonValue::String(value_)) => Ok(Query::Lte(key, value_)), + ("$lte", _) => Err("$lte must be used with string"), + ("$like", JsonValue::String(value_)) => Ok(Query::Like(key, value_)), + ("$like", _) => Err("$like must be used with string"), + ("$in", JsonValue::Array(values)) => { + let mut target_values: Vec = Vec::with_capacity(values.len()); + + for v in values.into_iter() { + if let JsonValue::String(s) = v { + target_values.push(s); + } else { + return Err("$in must be used with array of strings"); + } + } + + Ok(Query::In(key, target_values)) + } + ("$in", _) => Err("$in must be used with array of strings"), + (_, _) => Err("Unknown operator"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rand::distributions::Alphanumeric; + use rand::{thread_rng, Rng}; + use serde_json::json; + + fn _random_string(len: usize) -> String { + String::from_utf8(thread_rng().sample_iter(&Alphanumeric).take(len).collect()).unwrap() + } + + /// parse + #[test] + fn test_simple_operator_empty_json_parse() { + let json = "{}"; + + let query: Query = ::serde_json::from_str(json).unwrap(); + + let expected = Query::And(vec![]); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_explicit_empty_and_parse() { + let json = r#"{"$and":[]}"#; + + let query: Query = ::serde_json::from_str(json).unwrap(); + + let expected = Query::And(vec![]); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_empty_or_parse() { + let json = r#"{"$or":[]}"#; + + let query: Query = ::serde_json::from_str(json).unwrap(); + + let expected = Query::And(vec![]); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_empty_not_parse() { + let json = r#"{"$not":{}}"#; + + let query: Query = ::serde_json::from_str(json).unwrap(); + + let expected = Query::Not(Box::new(Query::And(vec![]))); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_eq_plaintext_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":"{}"}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Eq(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$neq":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Neq(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$gt":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Gt(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$gte":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Gte(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$lt":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Lt(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_lte_plaintext_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$lte":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Lte(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$like":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Like(name1, value1); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_in_plaintext_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"{}":{{"$in":["{}"]}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::In(name1, vec![value1]); + + assert_eq!(query, expected); + } + + #[test] + fn test_simple_operator_in_plaintexts_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let value2 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"{}":{{"$in":["{}","{}","{}"]}}}}"#, + name1, value1, value2, value3 + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::In(name1, vec![value1, value2, value3]); + + assert_eq!(query, expected); + } + + #[test] + fn test_exist_parse_string() { + let name1 = _random_string(10); + + let json = format!(r#"{{"$exist":"{}"}}"#, name1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Exist(vec![name1]); + + assert_eq!(query, expected); + } + + #[test] + fn test_exist_parse_array() { + let name1 = _random_string(10); + let name2 = _random_string(10); + + let json = format!(r#"{{"$exist":["{}","{}"]}}"#, name1, name2); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Exist(vec![name1, name2]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_exist() { + let name1 = _random_string(10); + let name2 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"$exist":"{}"}},{{"$exist":"{}"}}]}}"#, + name1, name2 + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Exist(vec![name1]), Query::Exist(vec![name2])]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":"{}"}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Eq(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Neq(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Gt(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Gte(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Lt(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_lte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Lte(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Like(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_in_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::In(name1, vec![value1])]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_one_not_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$and":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![Query::Not(Box::new(Query::Eq(name1, value1)))]); + + assert_eq!(query, expected); + } + + #[test] + fn test_short_and_with_multiple_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"{}":"{}","{}":"{}","{}":"{}"}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + let mut clauses = vec![ + Query::Eq(name1, value1), + Query::Eq(name2, value2), + Query::Eq(name3, value3), + ]; + clauses.sort(); + + let expected = Query::And(clauses); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Eq(name1, value1), + Query::Eq(name2, value2), + Query::Eq(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Neq(name1, value1), + Query::Neq(name2, value2), + Query::Neq(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Gt(name1, value1), + Query::Gt(name2, value2), + Query::Gt(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Gte(name1, value1), + Query::Gte(name2, value2), + Query::Gte(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Lt(name1, value1), + Query::Lt(name2, value2), + Query::Lt(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_lte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Lte(name1, value1), + Query::Lte(name2, value2), + Query::Lte(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Like(name1, value1), + Query::Like(name2, value2), + Query::Like(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_in_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::In(name1, vec![value1]), + Query::In(name2, vec![value2]), + Query::In(name3, vec![value3]), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_not_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Not(Box::new(Query::Eq(name1, value1))), + Query::Not(Box::new(Query::Eq(name2, value2))), + Query::Not(Box::new(Query::Eq(name3, value3))), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_with_multiple_mixed_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8a = _random_string(10); + let value8b = _random_string(10); + let name9 = _random_string(10); + let value9 = _random_string(10); + + let json = format!( + r#"{{"$and":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8a, + value8b, + name9, + value9, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![ + Query::Eq(name1, value1), + Query::Neq(name2, value2), + Query::Gt(name3, value3), + Query::Gte(name4, value4), + Query::Lt(name5, value5), + Query::Lte(name6, value6), + Query::Like(name7, value7), + Query::In(name8, vec![value8a, value8b]), + Query::Not(Box::new(Query::Eq(name9, value9))), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":"{}"}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Eq(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Neq(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Gt(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Gte(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Lt(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_lte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Lte(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Like(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_in_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::In(name1, vec![value1])]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_one_not_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$or":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Not(Box::new(Query::Eq(name1, value1)))]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Eq(name1, value1), + Query::Eq(name2, value2), + Query::Eq(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Neq(name1, value1), + Query::Neq(name2, value2), + Query::Neq(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Gt(name1, value1), + Query::Gt(name2, value2), + Query::Gt(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Gte(name1, value1), + Query::Gte(name2, value2), + Query::Gte(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Lt(name1, value1), + Query::Lt(name2, value2), + Query::Lt(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_lte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Lte(name1, value1), + Query::Lte(name2, value2), + Query::Lte(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Like(name1, value1), + Query::Like(name2, value2), + Query::Like(name3, value3), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_in_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::In(name1, vec![value1]), + Query::In(name2, vec![value2]), + Query::In(name3, vec![value3]), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_not_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Not(Box::new(Query::Eq(name1, value1))), + Query::Not(Box::new(Query::Eq(name2, value2))), + Query::Not(Box::new(Query::Eq(name3, value3))), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_or_with_multiple_mixed_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8a = _random_string(10); + let value8b = _random_string(10); + let name9 = _random_string(10); + let value9 = _random_string(10); + + let json = format!( + r#"{{"$or":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8a, + value8b, + name9, + value9, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![ + Query::Eq(name1, value1), + Query::Neq(name2, value2), + Query::Gt(name3, value3), + Query::Gte(name4, value4), + Query::Lt(name5, value5), + Query::Lte(name6, value6), + Query::Like(name7, value7), + Query::In(name8, vec![value8a, value8b]), + Query::Not(Box::new(Query::Eq(name9, value9))), + ]); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_eq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":"{}"}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Eq(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_neq_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$neq":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Neq(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_gt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$gt":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Gt(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_gte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$gte":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Gte(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_lt_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$lt":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Lt(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_lte_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$lte":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Lte(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_like_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$like":"{}"}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::Like(name1, value1))); + + assert_eq!(query, expected); + } + + #[test] + fn test_not_with_one_in_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let json = format!(r#"{{"$not":{{"{}":{{"$in":["{}"]}}}}}}"#, name1, value1); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::In(name1, vec![value1]))); + + assert_eq!(query, expected); + } + + #[test] + fn test_and_or_not_complex_case_parse() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8 = _random_string(10); + + let json = format!( + r#"{{"$not":{{"$and":[{{"{}":"{}"}},{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"$not":{{"{}":{{"$lte":"{}"}}}}}},{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"$not":{{"{}":{{"$gte":"{}"}}}}}}]}}]}},{{"$not":{{"{}":{{"$like":"{}"}}}}}},{{"$and":[{{"{}":"{}"}},{{"$not":{{"{}":{{"$neq":"{}"}}}}}}]}}]}}}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8, + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Not(Box::new(Query::And(vec![ + Query::Eq(name1, value1), + Query::Or(vec![ + Query::Gt(name2, value2), + Query::Not(Box::new(Query::Lte(name3, value3))), + Query::And(vec![ + Query::Lt(name4, value4), + Query::Not(Box::new(Query::Gte(name5, value5))), + ]), + ]), + Query::Not(Box::new(Query::Like(name6, value6))), + Query::And(vec![ + Query::Eq(name7, value7), + Query::Not(Box::new(Query::Neq(name8, value8))), + ]), + ]))); + + assert_eq!(query, expected); + } + + /// to string + #[test] + fn test_simple_operator_empty_and_to_string() { + let query = Query::And(vec![]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = "{}"; + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_empty_or_to_string() { + let query = Query::Or(vec![]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = "{}"; + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_empty_not_to_string() { + let query = Query::Not(Box::new(Query::And(vec![]))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = r#"{"$not":{}}"#; + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Eq(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":"{}"}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Neq(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$neq":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_gt_plaintext_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Gt(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$gt":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Gte(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$gte":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Lt(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$lt":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Lte(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$lte":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Like(name1.clone(), value1.clone()); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$like":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::In(name1.clone(), vec![value1.clone()]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"{}":{{"$in":["{}"]}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_simple_operator_in_multimply_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let value2 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::In( + name1.clone(), + vec![value1.clone(), value2.clone(), value3.clone()], + ); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"{}":{{"$in":["{}","{}","{}"]}}}}"#, + name1, value1, value2, value3 + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Eq(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":"{}"}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Neq(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_gt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Gt(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Gte(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Lt(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Lte(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Like(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::In(name1.clone(), vec![value1.clone()])]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_one_not_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::And(vec![Query::Not(Box::new(Query::Eq( + name1.clone(), + value1.clone(), + )))]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$and":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Eq(name1.clone(), value1.clone()), + Query::Eq(name2.clone(), value2.clone()), + Query::Eq(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Neq(name1.clone(), value1.clone()), + Query::Neq(name2.clone(), value2.clone()), + Query::Neq(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_gt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Gt(name1.clone(), value1.clone()), + Query::Gt(name2.clone(), value2.clone()), + Query::Gt(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Gte(name1.clone(), value1.clone()), + Query::Gte(name2.clone(), value2.clone()), + Query::Gte(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Lt(name1.clone(), value1.clone()), + Query::Lt(name2.clone(), value2.clone()), + Query::Lt(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Lte(name1.clone(), value1.clone()), + Query::Lte(name2.clone(), value2.clone()), + Query::Lte(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Like(name1.clone(), value1.clone()), + Query::Like(name2.clone(), value2.clone()), + Query::Like(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::In(name1.clone(), vec![value1.clone()]), + Query::In(name2.clone(), vec![value2.clone()]), + Query::In(name3.clone(), vec![value3.clone()]), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_not_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::And(vec![ + Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))), + Query::Not(Box::new(Query::Eq(name2.clone(), value2.clone()))), + Query::Not(Box::new(Query::Eq(name3.clone(), value3.clone()))), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_with_multiple_mixed_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8a = _random_string(10); + let value8b = _random_string(10); + let name9 = _random_string(10); + let value9 = _random_string(10); + + let query = Query::And(vec![ + Query::Eq(name1.clone(), value1.clone()), + Query::Neq(name2.clone(), value2.clone()), + Query::Gt(name3.clone(), value3.clone()), + Query::Gte(name4.clone(), value4.clone()), + Query::Lt(name5.clone(), value5.clone()), + Query::Lte(name6.clone(), value6.clone()), + Query::Like(name7.clone(), value7.clone()), + Query::In(name8.clone(), vec![value8a.clone(), value8b.clone()]), + Query::Not(Box::new(Query::Eq(name9.clone(), value9.clone()))), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$and":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8a, + value8b, + name9, + value9, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Eq(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":"{}"}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Neq(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_gt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Gt(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Gte(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Lt(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Lte(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Like(name1.clone(), value1.clone())]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::In(name1.clone(), vec![value1.clone()])]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_one_not_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Or(vec![Query::Not(Box::new(Query::Eq( + name1.clone(), + value1.clone(), + )))]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$or":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Eq(name1.clone(), value1.clone()), + Query::Eq(name2.clone(), value2.clone()), + Query::Eq(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Neq(name1.clone(), value1.clone()), + Query::Neq(name2.clone(), value2.clone()), + Query::Neq(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_gt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Gt(name1.clone(), value1.clone()), + Query::Gt(name2.clone(), value2.clone()), + Query::Gt(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Gte(name1.clone(), value1.clone()), + Query::Gte(name2.clone(), value2.clone()), + Query::Gte(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Lt(name1.clone(), value1.clone()), + Query::Lt(name2.clone(), value2.clone()), + Query::Lt(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Lte(name1.clone(), value1.clone()), + Query::Lte(name2.clone(), value2.clone()), + Query::Lte(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Like(name1.clone(), value1.clone()), + Query::Like(name2.clone(), value2.clone()), + Query::Like(name3.clone(), value3.clone()), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::In(name1.clone(), vec![value1.clone()]), + Query::In(name2.clone(), vec![value2.clone()]), + Query::In(name3.clone(), vec![value3.clone()]), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_not_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + + let query = Query::Or(vec![ + Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))), + Query::Not(Box::new(Query::Eq(name2.clone(), value2.clone()))), + Query::Not(Box::new(Query::Eq(name3.clone(), value3.clone()))), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, value1, name2, value2, name3, value3, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_or_with_multiple_mixed_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8a = _random_string(10); + let value8b = _random_string(10); + let name9 = _random_string(10); + let value9 = _random_string(10); + + let query = Query::Or(vec![ + Query::Eq(name1.clone(), value1.clone()), + Query::Neq(name2.clone(), value2.clone()), + Query::Gt(name3.clone(), value3.clone()), + Query::Gte(name4.clone(), value4.clone()), + Query::Lt(name5.clone(), value5.clone()), + Query::Lte(name6.clone(), value6.clone()), + Query::Like(name7.clone(), value7.clone()), + Query::In(name8.clone(), vec![value8a.clone(), value8b.clone()]), + Query::Not(Box::new(Query::Eq(name9.clone(), value9.clone()))), + ]); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$or":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8a, + value8b, + name9, + value9, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_eq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":"{}"}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_neq_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Neq(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$neq":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_gt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Gt(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$gt":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_gte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Gte(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$gte":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_lt_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Lt(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$lt":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_lte_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Lte(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$lte":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_like_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::Like(name1.clone(), value1.clone()))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$like":"{}"}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_not_with_one_in_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + + let query = Query::Not(Box::new(Query::In(name1.clone(), vec![value1.clone()]))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!(r#"{{"$not":{{"{}":{{"$in":["{}"]}}}}}}"#, name1, value1); + + assert_eq!(json, expected); + } + + #[test] + fn test_and_or_not_complex_case_to_string() { + let name1 = _random_string(10); + let value1 = _random_string(10); + let name2 = _random_string(10); + let value2 = _random_string(10); + let name3 = _random_string(10); + let value3 = _random_string(10); + let name4 = _random_string(10); + let value4 = _random_string(10); + let name5 = _random_string(10); + let value5 = _random_string(10); + let name6 = _random_string(10); + let value6 = _random_string(10); + let name7 = _random_string(10); + let value7 = _random_string(10); + let name8 = _random_string(10); + let value8 = _random_string(10); + + let query = Query::Not(Box::new(Query::And(vec![ + Query::Eq(name1.clone(), value1.clone()), + Query::Or(vec![ + Query::Gt(name2.clone(), value2.clone()), + Query::Not(Box::new(Query::Lte(name3.clone(), value3.clone()))), + Query::And(vec![ + Query::Lt(name4.clone(), value4.clone()), + Query::Not(Box::new(Query::Gte(name5.clone(), value5.clone()))), + ]), + ]), + Query::Not(Box::new(Query::Like(name6.clone(), value6.clone()))), + Query::And(vec![ + Query::Eq(name7.clone(), value7.clone()), + Query::Not(Box::new(Query::Neq(name8.clone(), value8.clone()))), + ]), + ]))); + + let json = ::serde_json::to_string(&query).unwrap(); + + let expected = format!( + r#"{{"$not":{{"$and":[{{"{}":"{}"}},{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"$not":{{"{}":{{"$lte":"{}"}}}}}},{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"$not":{{"{}":{{"$gte":"{}"}}}}}}]}}]}},{{"$not":{{"{}":{{"$like":"{}"}}}}}},{{"$and":[{{"{}":"{}"}},{{"$not":{{"{}":{{"$neq":"{}"}}}}}}]}}]}}}}"#, + name1, + value1, + name2, + value2, + name3, + value3, + name4, + value4, + name5, + value5, + name6, + value6, + name7, + value7, + name8, + value8, + ); + + assert_eq!(json, expected); + } + + #[test] + fn test_old_format() { + let name1 = _random_string(10); + let name2 = _random_string(10); + let value1 = _random_string(10); + let value2 = _random_string(10); + + let json = format!( + r#"[{{"{}":"{}"}}, {{"{}":"{}"}}]"#, + name1, value1, name2, value2 + ); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Eq(name1, value1), Query::Eq(name2, value2)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_old_format_empty() { + let json = format!(r#"[]"#); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::And(vec![]); + + assert_eq!(query, expected); + } + + #[test] + fn test_old_format_with_nulls() { + let name1 = _random_string(10); + let name2 = _random_string(10); + let value1 = _random_string(10); + + let json = json!(vec![ + json ! ({name1.clone(): value1.clone()}), + json!({ name2.clone(): ::serde_json::Value::Null }) + ]) + .to_string(); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + let expected = Query::Or(vec![Query::Eq(name1, value1)]); + + assert_eq!(query, expected); + } + + #[test] + fn test_optimise_and() { + let json = r#"{}"#; + + let query: Query = ::serde_json::from_str(json).unwrap(); + + assert_eq!(query.optimise(), None); + } + + #[test] + fn test_optimise_or() { + let json = r#"[]"#; + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + assert_eq!(query.optimise(), None); + } + + #[test] + fn test_optimise_single_nested_and() { + let json = json!({ + "$and": [ + { + "$and": [] + } + ] + }) + .to_string(); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + assert_eq!(query.optimise(), None); + } + + #[test] + fn test_optimise_several_nested_and() { + let json = json!({ + "$and": [ + { + "$and": [] + }, + { + "$and": [] + } + ] + }) + .to_string(); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + assert_eq!(query.optimise(), None); + } + + #[test] + fn test_optimise_single_nested_or() { + let json = json!({ + "$and": [ + { + "$or": [] + } + ] + }) + .to_string(); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + assert_eq!(query.optimise(), None); + } + + #[test] + fn test_optimise_several_nested_or() { + let json = json!({ + "$and": [ + { + "$or": [] + }, + { + "$or": [] + } + ] + }) + .to_string(); + + let query: Query = ::serde_json::from_str(&json).unwrap(); + + assert_eq!(query.optimise(), None); + } +} From a4bb17cfb5c207c29f5ba441a54c4c54f9fcf5e8 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 29 Apr 2021 09:13:45 -0700 Subject: [PATCH 2/5] remove pack and random functions from indy_utils; clean up dependencies Signed-off-by: Andrew Whitehead --- indy-utils/Cargo.toml | 25 +- indy-utils/src/did.rs | 2 +- indy-utils/src/error.rs | 14 - indy-utils/src/hash.rs | 16 +- indy-utils/src/keys/mod.rs | 15 +- indy-utils/src/keys/types.rs | 120 -- indy-utils/src/lib.rs | 29 +- indy-utils/src/pack/alg.rs | 361 ---- indy-utils/src/pack/mod.rs | 6 - indy-utils/src/pack/nacl_box.rs | 138 -- indy-utils/src/pack/types.rs | 79 - indy-utils/src/random.rs | 57 - indy-utils/src/wql.rs | 2955 ------------------------------- 13 files changed, 25 insertions(+), 3792 deletions(-) delete mode 100644 indy-utils/src/pack/alg.rs delete mode 100644 indy-utils/src/pack/mod.rs delete mode 100644 indy-utils/src/pack/nacl_box.rs delete mode 100644 indy-utils/src/pack/types.rs delete mode 100644 indy-utils/src/random.rs delete mode 100644 indy-utils/src/wql.rs diff --git a/indy-utils/Cargo.toml b/indy-utils/Cargo.toml index ca9712f..15b2756 100644 --- a/indy-utils/Cargo.toml +++ b/indy-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "indy-utils" -version = "0.3.9" +version = "0.4.0" authors = ["Hyperledger Indy Contributors "] description = "Utilities for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." edition = "2018" @@ -16,34 +16,27 @@ path = "src/lib.rs" crate-type = ["rlib"] [features] -default = ["ed25519", "hash", "pack", "txn_signature", "wql"] +default = ["ed25519", "hash", "txn_signature", "wql"] base64 = ["base64_rs"] -cl = ["ursa", "ursa/cl"] -cl_native = ["ursa", "ursa/cl_native"] ed25519 = ["ursa", "ursa/ed25519", "ursa/x25519"] -hash = ["ursa", "ursa/sha2"] -pack = ["base64", "chacha20poly1305", "crypto_box", "ed25519", "serde_support", "ursa", "ursa/blake2"] -serde_support = ["serde", "serde_json", "ursa/serde"] -txn_signature = ["hash", "serde_support"] -wql = [] +hash = ["sha2"] +txn_signature = ["hex", "sha2", "serde", "serde_json"] +wql = ["indy-wql", "serde", "serde_json"] [dependencies] aead = "0.3" base64_rs = { package = "base64", version = "0.12", optional = true } bs58 = "0.3" -chacha20 = "0.6" -chacha20poly1305 = { version = "0.7", default-features = false, features = ["alloc", "chacha20"], optional = true } -crypto_box = { version = "0.2", optional = true } -hex = "0.4" +hex = { version = "0.4", optional = true } +indy-wql = { version = "0.4", optional = true, path = "../indy-wql" } once_cell = "1.4" -rand = "0.7" regex = "1.3" serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } -tempfile = { version = "3.1", optional = true } +sha2 = { version = "0.9", optional = true } thiserror = "1.0" ursa = { version = "0.3.5", default-features = false, optional = true } -zeroize = { version = "1.1", features = ["zeroize_derive"] } +zeroize = { version = "1.1" } [dev-dependencies] async-global-executor = "1.2" diff --git a/indy-utils/src/did.rs b/indy-utils/src/did.rs index eea0147..77d540a 100644 --- a/indy-utils/src/did.rs +++ b/indy-utils/src/did.rs @@ -125,7 +125,7 @@ impl Validatable for ShortDidValue { } } -#[cfg(test)] +#[cfg(all(test, feature = "ed25519"))] mod tests { use super::*; use crate::keys::EncodedVerKey; diff --git a/indy-utils/src/error.rs b/indy-utils/src/error.rs index 3a8352a..73af47b 100644 --- a/indy-utils/src/error.rs +++ b/indy-utils/src/error.rs @@ -124,20 +124,6 @@ impl From for ConversionError { } } -#[cfg(any(feature = "cl", feature = "cl_native"))] -impl From for ConversionError { - fn from(err: ursa::errors::UrsaCryptoError) -> Self { - Self::from(err.to_string()) - } -} - -#[cfg(any(feature = "cl", feature = "cl_native"))] -impl From for EncryptionError { - fn from(err: ursa::errors::UrsaCryptoError) -> Self { - Self::from(err.to_string()) - } -} - impl From for ConversionError { fn from(err: ValidationError) -> Self { Self { diff --git a/indy-utils/src/hash.rs b/indy-utils/src/hash.rs index d9d5d35..76da166 100644 --- a/indy-utils/src/hash.rs +++ b/indy-utils/src/hash.rs @@ -1,4 +1,4 @@ -pub use ursa::hash::sha2::Digest; +pub use sha2::Digest; use super::ValidationError; @@ -10,7 +10,7 @@ macro_rules! hash_type { #[allow(non_snake_case)] pub mod $modname { use once_cell::sync::Lazy; - use ursa::hash::sha2::Digest; + use sha2::Digest; pub type DigestType = $digest; @@ -30,7 +30,7 @@ macro_rules! hash_type { } } -hash_type!(SHA256, ursa::hash::sha2::Sha256, "Sha256 hash"); +hash_type!(SHA256, sha2::Sha256, "Sha256 hash"); /// A trait for producing hashes of merkle tree leaves and nodes pub trait TreeHash { @@ -49,9 +49,9 @@ impl TreeHash for H { T: Hashable, { let mut ctx = Self::new(); - ctx.input(&[0x00]); + ctx.update(&[0x00]); leaf.update_context(&mut ctx)?; - Ok(ctx.result().to_vec()) + Ok(ctx.finalize().to_vec()) } fn hash_nodes(left: &T, right: &T) -> Result, ValidationError> @@ -59,10 +59,10 @@ impl TreeHash for H { T: Hashable, { let mut ctx = Self::new(); - ctx.input(&[0x01]); + ctx.update(&[0x01]); left.update_context(&mut ctx)?; right.update_context(&mut ctx)?; - Ok(ctx.result().to_vec()) + Ok(ctx.finalize().to_vec()) } } @@ -95,7 +95,7 @@ pub trait Hashable { impl> Hashable for T { fn update_context(&self, context: &mut D) -> Result<(), ValidationError> { - Ok(context.input(self.as_ref())) + Ok(context.update(self.as_ref())) } } diff --git a/indy-utils/src/keys/mod.rs b/indy-utils/src/keys/mod.rs index 94d2ed8..469ec83 100644 --- a/indy-utils/src/keys/mod.rs +++ b/indy-utils/src/keys/mod.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "ed25519")] -use once_cell::sync::Lazy; - #[cfg(feature = "ed25519")] use ursa::signatures::{ed25519::Ed25519Sha512, SignatureScheme}; @@ -11,10 +8,7 @@ use super::error::ConversionError; use super::{Validatable, ValidationError}; mod types; -pub use types::{ArrayKey, KeyEncoding, KeyType}; - -#[cfg(feature = "ed25519")] -static ED25519_SIGNER: Lazy = Lazy::new(|| Ed25519Sha512::new()); +pub use types::{KeyEncoding, KeyType}; /// Build an encoded verkey pub fn build_full_verkey(dest: &str, key: &str) -> Result { @@ -41,7 +35,7 @@ impl PrivateKey { let alg = alg.unwrap_or_default(); match alg { KeyType::ED25519 => { - let (_pk, sk) = ED25519_SIGNER + let (_pk, sk) = Ed25519Sha512 .keypair(None) .map_err(|_| "Error creating signing key")?; Ok(Self::new(sk, Some(KeyType::ED25519))) @@ -86,7 +80,7 @@ impl PrivateKey { match self.alg { KeyType::ED25519 => { let sk = ursa::keys::PrivateKey(self.key_bytes()); - Ok(ED25519_SIGNER + Ok(Ed25519Sha512 .sign(message.as_ref(), &sk) .map_err(|err| format!("Error signing payload: {}", err))?) } @@ -189,7 +183,7 @@ impl VerKey { match self.alg { KeyType::ED25519 => { let vk = ursa::keys::PublicKey(self.key_bytes()); - Ok(ED25519_SIGNER + Ok(Ed25519Sha512 .verify(message.as_ref(), signature.as_ref(), &vk) .map_err(|err| format!("Error validating message signature: {}", err))?) } @@ -503,6 +497,7 @@ mod tests { assert!(vk.verify_signature(&message, &sig).unwrap()); } + #[cfg(feature = "ed25519")] #[test] fn validate_keys() { let sk = PrivateKey::generate(None).unwrap(); diff --git a/indy-utils/src/keys/types.rs b/indy-utils/src/keys/types.rs index af891cb..2bd0dd2 100644 --- a/indy-utils/src/keys/types.rs +++ b/indy-utils/src/keys/types.rs @@ -1,9 +1,3 @@ -use std::cmp::Ordering; - -use aead::generic_array::{ArrayLength, GenericArray}; - -use crate::random::random_array; - pub const KEY_ENC_BASE58: &'static str = "base58"; pub const KEY_TYPE_ED25519: &'static str = "ed25519"; @@ -126,117 +120,3 @@ impl From for KeyEncoding { Self::from_str(&value) } } - -/// A secure key representation for fixed-length keys -#[derive(Clone, Debug, Hash, Zeroize)] -pub struct ArrayKey>(GenericArray); - -impl> ArrayKey { - pub const SIZE: usize = L::USIZE; - - #[inline] - pub fn from_slice>(data: D) -> Self { - Self(GenericArray::from_slice(data.as_ref()).clone()) - } - - #[inline] - pub fn extract(self) -> GenericArray { - self.0 - } - - #[inline] - pub fn random() -> Self { - Self(random_array()) - } -} - -impl> Default for ArrayKey { - #[inline] - fn default() -> Self { - Self(GenericArray::default()) - } -} - -impl> From> for ArrayKey { - fn from(key: GenericArray) -> Self { - Self(key) - } -} - -impl> std::ops::Deref for ArrayKey { - type Target = GenericArray; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl> std::ops::DerefMut for ArrayKey { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl> PartialEq for ArrayKey { - fn eq(&self, other: &Self) -> bool { - **self == **other - } -} -impl> Eq for ArrayKey {} - -impl> PartialOrd for ArrayKey { - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&*other) - } -} -impl> Ord for ArrayKey { - fn cmp(&self, other: &Self) -> Ordering { - self.0.cmp(&*other) - } -} - -#[cfg(feature = "serde")] -mod serde { - use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; - - use super::{ArrayKey, ArrayLength, GenericArray}; - - impl> Serialize for ArrayKey { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(hex::encode(&self.0.as_slice()).as_str()) - } - } - - impl<'a, L: ArrayLength> Deserialize<'a> for ArrayKey { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'a>, - { - deserializer.deserialize_str(KeyVisitor { - _pd: std::marker::PhantomData, - }) - } - } - - struct KeyVisitor> { - _pd: std::marker::PhantomData, - } - - impl<'a, L: ArrayLength> Visitor<'a> for KeyVisitor { - type Value = ArrayKey; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - formatter.write_str(stringify!($name)) - } - - fn visit_str(self, value: &str) -> Result, E> - where - E: serde::de::Error, - { - let key = hex::decode(value).map_err(E::custom)?; - Ok(ArrayKey(GenericArray::clone_from_slice(key.as_slice()))) - } - } -} diff --git a/indy-utils/src/lib.rs b/indy-utils/src/lib.rs index 5147fb0..4c54f36 100644 --- a/indy-utils/src/lib.rs +++ b/indy-utils/src/lib.rs @@ -1,14 +1,9 @@ pub extern crate aead; -pub extern crate hex; - -#[cfg(any(feature = "serde_support", test))] +#[cfg(any(feature = "serde", test))] #[macro_use] pub extern crate serde; -#[macro_use] -pub extern crate zeroize; - /// Common macros #[macro_use] mod macros; @@ -35,9 +30,6 @@ pub mod did; /// Indy signing keys and verification keys pub mod keys; -/// Random number generation -pub mod random; - /// Base64 encoding and decoding #[cfg(feature = "base64")] pub mod base64; @@ -46,27 +38,10 @@ pub mod base64; #[cfg(feature = "hash")] pub mod hash; -/// Message packing and unpacking -#[cfg(feature = "pack")] -pub mod pack; - /// Generation of normalized ledger transaction for signing #[cfg(feature = "txn_signature")] pub mod txn_signature; /// Wallet query language #[cfg(feature = "wql")] -pub mod wql; - -/// Re-export ursa to avoid version conflicts -#[cfg(any( - feature = "cl", - feature = "cl_native", - feature = "ed25519", - feature = "hash", - feature = "pack", - feature = "wallet_key" -))] -pub extern crate ursa; - -pub extern crate once_cell; +pub use indy_wql as wql; diff --git a/indy-utils/src/pack/alg.rs b/indy-utils/src/pack/alg.rs deleted file mode 100644 index 6fe0166..0000000 --- a/indy-utils/src/pack/alg.rs +++ /dev/null @@ -1,361 +0,0 @@ -use chacha20poly1305::{ - aead::{generic_array::typenum::Unsigned, Aead, NewAead, Payload}, - ChaCha20Poly1305, Key as ChaChaKey, -}; - -use std::string::ToString; - -use super::nacl_box::*; -use super::types::*; -use crate::base64; -use crate::error::ConversionError; -use crate::keys::{ArrayKey, EncodedVerKey, PrivateKey}; -use crate::random::random_array; - -pub const PROTECTED_HEADER_ENC: &'static str = "xchacha20poly1305_ietf"; -pub const PROTECTED_HEADER_TYP: &'static str = "JWM/1.0"; -pub const PROTECTED_HEADER_ALG_AUTH: &'static str = "Authcrypt"; -pub const PROTECTED_HEADER_ALG_ANON: &'static str = "Anoncrypt"; - -type KeySize = ::KeySize; - -const NONCE_SIZE: usize = ::NonceSize::USIZE; -const TAG_SIZE: usize = ::TagSize::USIZE; - -pub fn pack_message>( - message: M, - receiver_list: Vec, - sender_key: Option, -) -> Result, ConversionError> { - // break early and error out if no receivers keys are provided - if receiver_list.is_empty() { - return Err("No message recipients".into()); - } - - // generate content encryption key that will encrypt `message` - let cek = ArrayKey::random(); - - let base64_protected = if let Some(sender_key) = sender_key { - // returns authcrypted pack_message format. See Wire message format HIPE for details - prepare_protected_authcrypt(&cek, receiver_list, &sender_key)? - } else { - // returns anoncrypted pack_message format. See Wire message format HIPE for details - prepare_protected_anoncrypt(&cek, receiver_list)? - }; - - // Use AEAD to encrypt `message` with "protected" data as "associated data" - let chacha = ChaCha20Poly1305::new(ChaChaKey::from_slice(&cek)); - let nonce = random_array(); - let payload = Payload { - aad: base64_protected.as_bytes(), - msg: message.as_ref(), - }; - let ciphertext = chacha - .encrypt(&nonce, payload) - .map_err(|_| "Error encrypting payload")?; - let iv = base64::encode_urlsafe(nonce); - let clen = ciphertext.len() - TAG_SIZE; - let tag = base64::encode_urlsafe(&ciphertext[clen..]); - let ciphertext = base64::encode_urlsafe(&ciphertext[..clen]); - - format_pack_message(&base64_protected, &ciphertext, &iv, &tag) -} - -fn prepare_protected_anoncrypt( - cek: &ArrayKey, - receiver_list: Vec, -) -> Result { - let mut encrypted_recipients_struct: Vec = Vec::with_capacity(receiver_list.len()); - - for their_vk in receiver_list { - // encrypt cek for recipient - let their_vk_x = their_vk.key_exchange()?; - let enc_cek = crypto_box_seal(their_vk_x.as_ref(), cek.as_ref())?; - - // create recipient struct and push to encrypted list - encrypted_recipients_struct.push(Recipient { - encrypted_key: base64::encode_urlsafe(enc_cek.as_slice()), - header: Header { - kid: their_vk.to_string(), - sender: None, - iv: None, - }, - }); - } - - base64_encode_protected(encrypted_recipients_struct, false) -} - -fn prepare_protected_authcrypt( - cek: &ArrayKey, - receiver_list: Vec, - sender_key: &PrivateKey, -) -> Result { - let mut encrypted_recipients_struct: Vec = vec![]; - - let sender_key_x = sender_key.key_exchange()?; - let sender_pk = sender_key.public_key()?.as_base58()?; - - for their_vk in receiver_list { - let their_vk_x = their_vk.key_exchange()?; - - // encrypt cek for recipient - let (enc_cek, iv) = crypto_box(their_vk_x.as_ref(), sender_key_x.as_ref(), &cek[..], None)?; - - // encrypt sender key for recipient - let enc_sender = crypto_box_seal(their_vk_x.as_ref(), sender_pk.encoded_key_bytes())?; - - // create recipient struct and push to encrypted list - encrypted_recipients_struct.push(Recipient { - encrypted_key: base64::encode_urlsafe(enc_cek.as_slice()), - header: Header { - kid: their_vk.to_string(), - sender: Some(base64::encode_urlsafe(enc_sender.as_slice())), - iv: Some(base64::encode_urlsafe(iv.as_slice())), - }, - }); - } - - base64_encode_protected(encrypted_recipients_struct, true) -} - -fn base64_encode_protected( - encrypted_recipients_struct: Vec, - alg_is_authcrypt: bool, -) -> Result { - let alg_val = if alg_is_authcrypt { - String::from(PROTECTED_HEADER_ALG_AUTH) - } else { - String::from(PROTECTED_HEADER_ALG_ANON) - }; - - // structure protected and base64URL encode it - let protected_struct = Protected { - enc: PROTECTED_HEADER_ENC.to_string(), - typ: PROTECTED_HEADER_TYP.to_string(), - alg: alg_val, - recipients: encrypted_recipients_struct, - }; - let protected_encoded = serde_json::to_string(&protected_struct) - .map_err(|err| format!("Failed to serialize protected field {}", err))?; - - Ok(base64::encode_urlsafe(protected_encoded.as_bytes())) -} - -fn format_pack_message( - base64_protected: &str, - ciphertext: &str, - iv: &str, - tag: &str, -) -> Result, ConversionError> { - // serialize pack message and return as vector of bytes - let jwe_struct = JWE { - protected: base64_protected.to_string(), - iv: iv.to_string(), - ciphertext: ciphertext.to_string(), - tag: tag.to_string(), - }; - - Ok(serde_json::to_vec(&jwe_struct)?) -} - -pub async fn unpack_message<'f>( - message: impl AsRef<[u8]>, - lookup: impl KeyLookup<'f>, -) -> Result<(Vec, EncodedVerKey, Option), ConversionError> { - let jwe = serde_json::from_slice(message.as_ref())?; - unpack_jwe(&jwe, lookup).await -} - -pub async fn unpack_jwe<'f>( - jwe_struct: &JWE, - lookup: impl KeyLookup<'f>, -) -> Result<(Vec, EncodedVerKey, Option), ConversionError> { - // decode protected data - let protected_decoded = base64::decode_urlsafe(&jwe_struct.protected)?; - let protected: Protected = serde_json::from_slice(&protected_decoded)?; - - // extract recipient that matches a key in the wallet - let (recipient, recip_pk, recip_sk) = unwrap_opt_or_return!( - find_unpack_recipient(protected, lookup).await?, - Err("No matching recipient found".into()) - ); - let is_auth_recipient = recipient.header.sender.is_some() && recipient.header.iv.is_some(); - - // get cek and sender data - let (sender_verkey_option, cek) = if is_auth_recipient { - let (send, cek) = unpack_cek_authcrypt(&recipient, &recip_sk)?; - (Some(send), cek) - } else { - let cek = unpack_cek_anoncrypt(&recipient, &recip_sk)?; - (None, cek) - }; - - // decrypt message - let chacha = ChaCha20Poly1305::new_varkey(&cek) - .map_err(|_| "Error creating unpack decryptor for cek")?; - let nonce = base64::decode_urlsafe(&jwe_struct.iv)?; - if nonce.len() != NONCE_SIZE { - return Err("Invalid size for message nonce".into()); - } - let mut ciphertext = base64::decode_urlsafe(&jwe_struct.ciphertext)?; - ciphertext.append(base64::decode_urlsafe(&jwe_struct.tag)?.as_mut()); - let payload = Payload { - aad: jwe_struct.protected.as_bytes(), - msg: ciphertext.as_slice(), - }; - let message = chacha - .decrypt(nonce.as_slice().into(), payload) - .map_err(|_| "Error decrypting message payload")?; - - Ok((message, recip_pk, sender_verkey_option)) -} - -fn unpack_cek_authcrypt( - recipient: &Recipient, - recip_sk: &PrivateKey, -) -> Result<(EncodedVerKey, Vec), ConversionError> { - let encrypted_key_vec = base64::decode_urlsafe(&recipient.encrypted_key)?; - let iv = base64::decode_urlsafe(&recipient.header.iv.as_ref().unwrap())?; - let enc_sender_vk = base64::decode_urlsafe(&recipient.header.sender.as_ref().unwrap())?; - - // decrypt sender_vk - let recip_pk = recip_sk.public_key()?; - let sender_vk_vec = crypto_box_seal_open( - recip_pk.key_exchange()?.as_ref(), - recip_sk.key_exchange()?.as_ref(), - &enc_sender_vk, - )?; - let sender_vk = EncodedVerKey::from_slice(&sender_vk_vec)?; - - // decrypt cek - let cek = crypto_box_open( - recip_sk.key_exchange()?.as_ref(), - sender_vk.key_exchange()?.as_ref(), - encrypted_key_vec.as_slice(), - iv.as_slice(), - )?; - - Ok((sender_vk, cek)) -} - -fn unpack_cek_anoncrypt( - recipient: &Recipient, - recip_sk: &PrivateKey, -) -> Result, ConversionError> { - let encrypted_key = base64::decode_urlsafe(&recipient.encrypted_key)?; - - // decrypt cek - let recip_pk = recip_sk.public_key()?; - let cek = crypto_box_seal_open( - recip_pk.key_exchange()?.as_ref(), - recip_sk.key_exchange()?.as_ref(), - &encrypted_key, - )?; - - Ok(cek) -} - -async fn find_unpack_recipient<'f>( - protected: Protected, - lookup: impl KeyLookup<'f>, -) -> Result, ConversionError> { - let mut recip_vks = Vec::::with_capacity(protected.recipients.len()); - for recipient in &protected.recipients { - let vk = EncodedVerKey::from_str(&recipient.header.kid)?; - recip_vks.push(vk); - } - if let Some((idx, sk)) = lookup.find(&recip_vks).await { - let recip = protected.recipients.into_iter().nth(idx).unwrap(); - let vk = recip_vks.into_iter().nth(idx).unwrap(); - Ok(Some((recip, vk, sk))) - } else { - Ok(None) - } -} - -#[cfg(test)] -mod tests { - use async_global_executor::block_on; - - use super::*; - - #[test] - fn test_anon_pack() { - let pk = PrivateKey::from_seed(b"000000000000000000000000000Test2") - .unwrap() - .public_key() - .unwrap() - .as_base58() - .unwrap(); - - let packed = pack_message(b"hello there", vec![pk], None); - assert!(packed.is_ok()); - } - - #[test] - fn test_auth_pack() { - let sk = PrivateKey::from_seed(b"000000000000000000000000000Test1").unwrap(); - let pk = PrivateKey::from_seed(b"000000000000000000000000000Test2") - .unwrap() - .public_key() - .unwrap() - .as_base58() - .unwrap(); - - let packed = pack_message(b"hello there", vec![pk], Some(sk)); - assert!(packed.is_ok()); - } - - #[test] - fn test_anon_pack_round_trip() { - let sk1 = PrivateKey::from_seed(b"000000000000000000000000000Test3").unwrap(); - let pk1 = sk1.public_key().unwrap().as_base58().unwrap(); - - let input_msg = b"hello there"; - let packed = pack_message(&input_msg, vec![pk1.clone()], None).unwrap(); - - let lookup = |find_pks: &Vec| { - for (idx, pk) in find_pks.into_iter().enumerate() { - if pk == &pk1 { - return Some((idx, sk1.clone())); - } - } - None - }; - - let lookup_fn = key_lookup_fn(lookup); - let result = unpack_message(&packed, &lookup_fn); - let (msg, p_recip, p_send) = block_on(result).unwrap(); - assert_eq!(msg, input_msg); - assert_eq!(p_recip, pk1); - assert_eq!(p_send, None); - } - - #[test] - fn test_auth_pack_round_trip() { - let sk1 = PrivateKey::from_seed(b"000000000000000000000000000Test3").unwrap(); - let pk1 = sk1.public_key().unwrap().as_base58().unwrap(); - let sk2 = PrivateKey::from_seed(b"000000000000000000000000000Test4").unwrap(); - let pk2 = sk2.public_key().unwrap().as_base58().unwrap(); - - let input_msg = b"hello there"; - let packed = pack_message(&input_msg, vec![pk2.clone()], Some(sk1.clone())).unwrap(); - - let lookup = |find_pks: &Vec| { - for (idx, pk) in find_pks.into_iter().enumerate() { - if pk == &pk2 { - return Some((idx, sk2.clone())); - } - } - None - }; - - let lookup_fn = key_lookup_fn(lookup); - let result = unpack_message(&packed, &lookup_fn); - let (msg, p_recip, p_send) = block_on(result).unwrap(); - assert_eq!(msg, input_msg); - assert_eq!(p_recip, pk2); - assert_eq!(p_send, Some(pk1)); - } -} diff --git a/indy-utils/src/pack/mod.rs b/indy-utils/src/pack/mod.rs deleted file mode 100644 index 59ed28b..0000000 --- a/indy-utils/src/pack/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod alg; -mod nacl_box; -mod types; - -pub use alg::{pack_message, unpack_message}; -pub use types::{key_lookup_fn, KeyLookup}; diff --git a/indy-utils/src/pack/nacl_box.rs b/indy-utils/src/pack/nacl_box.rs deleted file mode 100644 index 3d1a343..0000000 --- a/indy-utils/src/pack/nacl_box.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crypto_box::{ - self as cbox, - aead::{generic_array::typenum::Unsigned, Aead}, -}; -use ursa::blake2::{digest::Input, digest::VariableOutput, VarBlake2b}; - -use crate::error::{ConversionError, UnexpectedError, ValidationError}; -use crate::keys::{KeyType, PrivateKey}; -use crate::random::random_vec; - -const CBOX_NONCE_SIZE: usize = ::NonceSize::USIZE; - -fn crypto_box_key(key: F) -> Result -where - F: AsRef<[u8]>, - T: From<[u8; cbox::KEY_SIZE]>, -{ - let key = key.as_ref(); - if key.len() != cbox::KEY_SIZE { - Err(ValidationError::from("Invalid crypto box key length")) - } else { - let mut key_bytes = [0u8; cbox::KEY_SIZE]; - key_bytes.copy_from_slice(key); - Ok(T::from(key_bytes)) - } -} - -pub fn crypto_box_nonce( - ephemeral_pk: &[u8], - recip_pk: &[u8], -) -> Result<[u8; CBOX_NONCE_SIZE], UnexpectedError> { - let mut key_hash = VarBlake2b::new(CBOX_NONCE_SIZE).map_err(|_| "Error creating hasher")?; - key_hash.input(ephemeral_pk); - key_hash.input(recip_pk); - let mut nonce = [0u8; CBOX_NONCE_SIZE]; - key_hash.variable_result(|hash| nonce.clone_from_slice(hash)); - Ok(nonce) -} - -pub fn crypto_box( - recip_pk: &[u8], - sender_sk: &[u8], - message: &[u8], - nonce: Option>, -) -> Result<(Vec, Vec), ConversionError> { - let recip_pk: cbox::PublicKey = crypto_box_key(recip_pk)?; - let sender_sk: cbox::SecretKey = crypto_box_key(sender_sk)?; - let box_inst = cbox::SalsaBox::new(&recip_pk, &sender_sk); - - let nonce = if let Some(nonce) = nonce { - nonce.as_slice().into() - } else { - random_vec(CBOX_NONCE_SIZE) - }; - - let ciphertext = box_inst - .encrypt(nonce.as_slice().into(), message) - .map_err(|_| "Error encrypting box")?; - Ok((ciphertext, nonce)) -} - -pub fn crypto_box_open( - recip_sk: &[u8], - sender_pk: &[u8], - ciphertext: &[u8], - nonce: &[u8], -) -> Result, ConversionError> { - let recip_sk: cbox::SecretKey = crypto_box_key(recip_sk)?; - let sender_pk: cbox::PublicKey = crypto_box_key(sender_pk)?; - let box_inst = cbox::SalsaBox::new(&sender_pk, &recip_sk); - - let plaintext = box_inst - .decrypt(nonce.into(), ciphertext) - .map_err(|_| "Error decrypting box")?; - Ok(plaintext) -} - -pub fn crypto_box_seal(recip_pk: &[u8], message: &[u8]) -> Result, ConversionError> { - let sk = PrivateKey::generate(Some(KeyType::ED25519))?; - let ephem_sk = sk.key_exchange()?; - let ephem_sk_x: cbox::SecretKey = crypto_box_key(&ephem_sk)?; - assert_eq!(ephem_sk_x.to_bytes(), ephem_sk.as_ref()); - let ephem_pk_x = ephem_sk_x.public_key(); - - let nonce = crypto_box_nonce(ephem_pk_x.as_bytes(), &recip_pk)?.to_vec(); - let (mut boxed, _) = crypto_box(recip_pk, ephem_sk.as_ref(), message, Some(nonce))?; - - let mut result = Vec::::with_capacity(cbox::KEY_SIZE); // FIXME - result.extend_from_slice(ephem_pk_x.as_bytes()); - result.append(&mut boxed); - Ok(result) -} - -pub fn crypto_box_seal_open( - recip_pk: &[u8], - recip_sk: &[u8], - ciphertext: &[u8], -) -> Result, ConversionError> { - let ephem_pk = &ciphertext[..32]; - let boxed = &ciphertext[32..]; - - let nonce = crypto_box_nonce(&ephem_pk, &recip_pk)?; - let decode = crypto_box_open(recip_sk, ephem_pk, boxed, &nonce)?; - Ok(decode) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_box() { - let sk = hex::decode("07d0b594683bdb6af5f4eacb1a392687d580a58db196a752dca316dedb7d251d") - .unwrap(); - let pk = hex::decode("07d0b594683bdb6af5f4eacb1a392687d580a58db196a752dca316dedb7d251c") - .unwrap(); - let message = b"hello there"; - // let nonce = b"012345678912012345678912".to_vec(); - let (boxed, nonce) = crypto_box(&pk, &sk, message, None).unwrap(); - - let open = crypto_box_open(&sk, &pk, &boxed, &nonce).unwrap(); - assert_eq!(open, message); - } - - #[test] - fn test_box_seal() { - // let sk = SignKey::generate(Some(KeyType::ED25519)).unwrap(); - let sk = PrivateKey::from_seed(b"000000000000000000000000000Test0").unwrap(); - let pk_x = sk.public_key().unwrap().key_exchange().unwrap(); - let sk_x = sk.key_exchange().unwrap(); - - let message = b"hello there"; - let sealed = crypto_box_seal(&pk_x.as_ref(), message).unwrap(); - - let open = crypto_box_seal_open(&pk_x.as_ref(), &sk_x.as_ref(), &sealed).unwrap(); - assert_eq!(open, message); - } -} diff --git a/indy-utils/src/pack/types.rs b/indy-utils/src/pack/types.rs deleted file mode 100644 index 74491e1..0000000 --- a/indy-utils/src/pack/types.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::keys::{EncodedVerKey, PrivateKey}; - -use std::future::Future; - -#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] -pub struct JWE { - pub protected: String, - pub iv: String, - pub ciphertext: String, - pub tag: String, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] -pub struct Recipient { - pub encrypted_key: String, - pub header: Header, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] -pub struct Header { - pub kid: String, - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub iv: Option, - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub sender: Option, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] -pub struct Protected { - pub enc: String, - pub typ: String, - pub alg: String, - pub recipients: Vec, -} - -/// A trait for custom key lookup implementations used by unpack -pub trait KeyLookup<'f> { - fn find<'a>( - self, - key: &'a Vec, - ) -> std::pin::Pin> + Send + 'a>> - where - 'f: 'a; -} - -type KeyLookupCb<'a> = - Box) -> Option<(usize, PrivateKey)> + Send + Sync + 'a>; - -pub struct KeyLookupFn<'a> { - cb: KeyLookupCb<'a>, -} - -/// Create a `KeyLookup` from a callback function -pub fn key_lookup_fn<'a, F>(cb: F) -> KeyLookupFn<'a> -where - F: Fn(&Vec) -> Option<(usize, PrivateKey)> + Send + Sync + 'a, -{ - KeyLookupFn { - cb: Box::new(cb) as KeyLookupCb, - } -} - -impl<'a, 'l, 'r> KeyLookup<'l> for &'r KeyLookupFn<'a> -where - 'a: 'l, - 'r: 'a, -{ - fn find<'f>( - self, - keys: &'f Vec, - ) -> std::pin::Pin> + Send + 'f>> - where - 'l: 'f, - { - Box::pin(async move { (&self.cb)(keys) }) - } -} diff --git a/indy-utils/src/random.rs b/indy-utils/src/random.rs deleted file mode 100644 index d5e44c3..0000000 --- a/indy-utils/src/random.rs +++ /dev/null @@ -1,57 +0,0 @@ -use aead::generic_array::{ArrayLength, GenericArray}; -use chacha20::{ - cipher::{NewStreamCipher, SyncStreamCipher}, - ChaCha20, -}; -use rand::{rngs::OsRng, RngCore}; - -pub type SeedSize = ::KeySize; - -/// Fill a mutable slice with random data using the -/// system random number generator. -#[inline] -pub fn fill_random(value: &mut [u8]) { - OsRng.fill_bytes(value); -} - -/// Create a new `GenericArray` instance with random data. -#[inline] -pub fn random_array>() -> GenericArray { - let mut buf = GenericArray::default(); - fill_random(buf.as_mut_slice()); - buf -} - -/// Written to be compatible with randombytes_deterministic in libsodium, -/// used to generate a deterministic wallet raw key. -pub fn random_deterministic(seed: &GenericArray, len: usize) -> Vec { - let nonce = GenericArray::from_slice(b"LibsodiumDRG"); - let mut cipher = ChaCha20::new(seed, &nonce); - let mut data = vec![0; len]; - cipher.apply_keystream(data.as_mut_slice()); - data -} - -/// Create a new `Vec` instance with random data. -#[inline] -pub fn random_vec(sz: usize) -> Vec { - let mut buf = vec![0; sz]; - fill_random(buf.as_mut_slice()); - buf -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::base58; - - #[test] - fn random_det_expected() { - let key = GenericArray::from_slice(b"00000000000000000000000000000My1"); - let ret = random_deterministic(&key, 32); - assert_eq!( - base58::encode(ret), - "CwMHrEQJnwvuE8q9zbR49jyYtVxVBHNTjCPEPk1aV3cP" - ); - } -} diff --git a/indy-utils/src/wql.rs b/indy-utils/src/wql.rs deleted file mode 100644 index 41149ed..0000000 --- a/indy-utils/src/wql.rs +++ /dev/null @@ -1,2955 +0,0 @@ -use crate::ConversionError; - -#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum AbstractQuery { - And(Vec), - Or(Vec), - Not(Box), - Eq(K, V), - Neq(K, V), - Gt(K, V), - Gte(K, V), - Lt(K, V), - Lte(K, V), - Like(K, V), - In(K, Vec), - Exist(Vec), -} - -pub type Query = AbstractQuery; - -impl AbstractQuery { - pub fn optimise(self) -> Option { - match self { - Self::Not(boxed_query) => match boxed_query.optimise() { - None => None, - Some(Self::Not(nested_query)) => Some(*nested_query), - Some(other) => Some(Self::Not(Box::new(other))), - }, - Self::And(subqueries) => { - let mut subqueries: Vec = subqueries - .into_iter() - .flat_map(|query| query.optimise()) - .collect(); - - match subqueries.len() { - 0 => None, - 1 => Some(subqueries.remove(0)), - _ => Some(Self::And(subqueries)), - } - } - Self::Or(subqueries) => { - let mut subqueries: Vec = subqueries - .into_iter() - .flat_map(|query| query.optimise()) - .collect(); - - match subqueries.len() { - 0 => None, - 1 => Some(subqueries.remove(0)), - _ => Some(Self::Or(subqueries)), - } - } - Self::In(key, mut targets) if targets.len() == 1 => { - Some(Self::Eq(key, targets.remove(0))) - } - other => Some(other), - } - } - - pub fn map_names(self, f: &mut F) -> Result, ConversionError> - where - F: FnMut(K) -> Result, - { - self.map(f, &mut |_k, v| Ok(v)) - } - - pub fn map_values(self, f: &mut F) -> Result, ConversionError> - where - F: FnMut(&K, V) -> Result, - { - self.map(&mut |k| Ok(k), f) - } - - pub fn map( - self, - kf: &mut KF, - vf: &mut VF, - ) -> Result, ConversionError> - where - KF: FnMut(K) -> Result, - VF: FnMut(&K, V) -> Result, - { - match self { - Self::Eq(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Eq(kf(tag_name)?, tag_value)) - } - Self::Neq(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Neq(kf(tag_name)?, tag_value)) - } - Self::Gt(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Gt(kf(tag_name)?, tag_value)) - } - Self::Gte(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Gte(kf(tag_name)?, tag_value)) - } - Self::Lt(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Lt(kf(tag_name)?, tag_value)) - } - Self::Lte(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Lte(kf(tag_name)?, tag_value)) - } - Self::Like(tag_name, tag_value) => { - let tag_value = vf(&tag_name, tag_value)?; - Ok(AbstractQuery::::Like(kf(tag_name)?, tag_value)) - } - Self::In(tag_name, tag_values) => { - let tag_values = tag_values - .into_iter() - .map(|value| vf(&tag_name, value)) - .collect::, _>>()?; - Ok(AbstractQuery::::In(kf(tag_name)?, tag_values)) - } - Self::Exist(tag_names) => Ok(AbstractQuery::::Exist( - tag_names.into_iter().try_fold(vec![], |mut v, tag_name| { - v.push(kf(tag_name)?); - Result::<_, ConversionError>::Ok(v) - })?, - )), - Self::And(subqueries) => { - let subqueries = subqueries - .into_iter() - .map(|query| query.map(kf, vf)) - .collect::, _>>()?; - Ok(AbstractQuery::::And(subqueries)) - } - Self::Or(subqueries) => { - let subqueries = subqueries - .into_iter() - .map(|query| query.map(kf, vf)) - .collect::, _>>()?; - Ok(AbstractQuery::::Or(subqueries)) - } - Self::Not(boxed_query) => Ok(AbstractQuery::::Not(Box::new( - boxed_query.map(kf, vf)?, - ))), - } - } -} - -impl Default for AbstractQuery { - fn default() -> Self { - Self::And(Vec::new()) - } -} - -#[cfg(feature = "serde_support")] -mod serde_support { - use std::string; - - use serde::ser::{Serialize, Serializer}; - use serde::{de, Deserialize, Deserializer}; - use serde_json::{self, json, Value}; - - use super::{AbstractQuery, Query}; - - impl Serialize for AbstractQuery - where - for<'a> &'a K: Into, - V: Serialize, - { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.to_value().serialize(serializer) - } - } - - impl<'de> Deserialize<'de> for Query { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let v = Value::deserialize(deserializer)?; - - match v { - serde_json::Value::Object(map) => { - parse_query(map).map_err(|err| de::Error::missing_field(err)) - } - serde_json::Value::Array(array) => { - // cast old restrictions format to wql - let mut res: Vec = Vec::new(); - for sub_query in array { - let sub_query: serde_json::Map = sub_query - .as_object() - .ok_or_else(|| de::Error::custom("Restriction is invalid"))? - .clone() - .into_iter() - .filter(|&(_, ref v)| !v.is_null()) - .collect(); - - if !sub_query.is_empty() { - res.push(serde_json::Value::Object(sub_query)); - } - } - - let mut map = serde_json::Map::new(); - map.insert("$or".to_string(), serde_json::Value::Array(res)); - - parse_query(map).map_err(|err| de::Error::custom(err)) - } - _ => Err(de::Error::missing_field( - "Restriction must be either object or array", - )), - } - } - } - - impl AbstractQuery - where - for<'a> &'a K: Into, - V: Serialize, - { - fn to_value(&self) -> serde_json::Value { - match self { - Self::Eq(ref tag_name, ref tag_value) => json!({ tag_name: tag_value }), - Self::Neq(ref tag_name, ref tag_value) => json!({tag_name: {"$neq": tag_value}}), - Self::Gt(ref tag_name, ref tag_value) => json!({tag_name: {"$gt": tag_value}}), - Self::Gte(ref tag_name, ref tag_value) => json!({tag_name: {"$gte": tag_value}}), - Self::Lt(ref tag_name, ref tag_value) => json!({tag_name: {"$lt": tag_value}}), - Self::Lte(ref tag_name, ref tag_value) => json!({tag_name: {"$lte": tag_value}}), - Self::Like(ref tag_name, ref tag_value) => json!({tag_name: {"$like": tag_value}}), - Self::In(ref tag_name, ref tag_values) => json!({tag_name: {"$in":tag_values}}), - Self::Exist(ref tag_names) => { - json!({ "$exist": tag_names.iter().map(Into::into).collect::>() }) - } - Self::And(ref queries) => { - if !queries.is_empty() { - json!({ - "$and": queries.iter().map(|q| q.to_value()).collect::>() - }) - } else { - json!({}) - } - } - Self::Or(ref queries) => { - if !queries.is_empty() { - json!({ - "$or": queries.iter().map(|q| q.to_value()).collect::>() - }) - } else { - json!({}) - } - } - Self::Not(ref query) => json!({"$not": query.to_value()}), - } - } - } - - impl string::ToString for Query { - fn to_string(&self) -> String { - self.to_value().to_string() - } - } - - fn parse_query(map: serde_json::Map) -> Result { - let mut operators: Vec = Vec::new(); - - for (key, value) in map { - if let Some(operator_) = parse_operator(key, value)? { - operators.push(operator_); - } - } - - let query = if operators.len() == 1 { - operators.remove(0) - } else { - Query::And(operators) - }; - - Ok(query) - } - - fn parse_operator( - key: String, - value: serde_json::Value, - ) -> Result, &'static str> { - match (key.as_str(), value) { - ("$and", serde_json::Value::Array(values)) => { - if values.is_empty() { - Ok(None) - } else { - let operators: Vec = parse_list_operators(values)?; - Ok(Some(Query::And(operators))) - } - } - ("$and", _) => Err("$and must be array of JSON objects"), - ("$or", serde_json::Value::Array(values)) => { - if values.is_empty() { - Ok(None) - } else { - let operators: Vec = parse_list_operators(values)?; - Ok(Some(Query::Or(operators))) - } - } - ("$or", _) => Err("$or must be array of JSON objects"), - ("$not", serde_json::Value::Object(map)) => { - let operator = parse_query(map)?; - Ok(Some(Query::Not(Box::new(operator)))) - } - ("$not", _) => Err("$not must be JSON object"), - ("$exist", serde_json::Value::String(key)) => Ok(Some(Query::Exist(vec![key]))), - ("$exist", serde_json::Value::Array(keys)) => { - if keys.is_empty() { - Ok(None) - } else { - let mut ks = vec![]; - for key in keys { - if let serde_json::Value::String(key) = key { - ks.push(key); - } else { - return Err("$exist must be used with a string or array of strings"); - } - } - Ok(Some(Query::Exist(ks))) - } - } - ("$exist", _) => Err("$exist must be used with a string or array of strings"), - (_, serde_json::Value::String(value)) => Ok(Some(Query::Eq(key, value))), - (_, serde_json::Value::Object(map)) => { - if map.len() == 1 { - let (operator_name, value) = map.into_iter().next().unwrap(); - parse_single_operator(operator_name, key, value).map(|operator| Some(operator)) - } else { - Err("value must be JSON object of length 1") - } - } - (_, _) => Err("Unsupported value"), - } - } - - fn parse_list_operators(operators: Vec) -> Result, &'static str> { - let mut out_operators: Vec = Vec::with_capacity(operators.len()); - - for value in operators.into_iter() { - if let serde_json::Value::Object(map) = value { - let subquery = parse_query(map)?; - out_operators.push(subquery); - } else { - return Err("operator must be array of JSON objects"); - } - } - - Ok(out_operators) - } - - fn parse_single_operator( - operator_name: String, - key: String, - value: serde_json::Value, - ) -> Result { - match (&*operator_name, value) { - ("$neq", serde_json::Value::String(value_)) => Ok(Query::Neq(key, value_)), - ("$neq", _) => Err("$neq must be used with string"), - ("$gt", serde_json::Value::String(value_)) => Ok(Query::Gt(key, value_)), - ("$gt", _) => Err("$gt must be used with string"), - ("$gte", serde_json::Value::String(value_)) => Ok(Query::Gte(key, value_)), - ("$gte", _) => Err("$gte must be used with string"), - ("$lt", serde_json::Value::String(value_)) => Ok(Query::Lt(key, value_)), - ("$lt", _) => Err("$lt must be used with string"), - ("$lte", serde_json::Value::String(value_)) => Ok(Query::Lte(key, value_)), - ("$lte", _) => Err("$lte must be used with string"), - ("$like", serde_json::Value::String(value_)) => Ok(Query::Like(key, value_)), - ("$like", _) => Err("$like must be used with string"), - ("$in", serde_json::Value::Array(values)) => { - let mut target_values: Vec = Vec::with_capacity(values.len()); - - for v in values.into_iter() { - if let serde_json::Value::String(s) = v { - target_values.push(s); - } else { - return Err("$in must be used with array of strings"); - } - } - - Ok(Query::In(key, target_values)) - } - ("$in", _) => Err("$in must be used with array of strings"), - (_, _) => Err("Unknown operator"), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rand::distributions::Alphanumeric; - use rand::{thread_rng, Rng}; - use serde_json::json; - - fn _random_string(len: usize) -> String { - thread_rng().sample_iter(&Alphanumeric).take(len).collect() - } - - /// parse - #[test] - fn test_simple_operator_empty_json_parse() { - let json = "{}"; - - let query: Query = ::serde_json::from_str(json).unwrap(); - - let expected = Query::And(vec![]); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_explicit_empty_and_parse() { - let json = r#"{"$and":[]}"#; - - let query: Query = ::serde_json::from_str(json).unwrap(); - - let expected = Query::And(vec![]); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_empty_or_parse() { - let json = r#"{"$or":[]}"#; - - let query: Query = ::serde_json::from_str(json).unwrap(); - - let expected = Query::And(vec![]); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_empty_not_parse() { - let json = r#"{"$not":{}}"#; - - let query: Query = ::serde_json::from_str(json).unwrap(); - - let expected = Query::Not(Box::new(Query::And(vec![]))); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_eq_plaintext_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":"{}"}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Eq(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$neq":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Neq(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$gt":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Gt(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$gte":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Gte(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$lt":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Lt(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_lte_plaintext_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$lte":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Lte(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$like":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Like(name1, value1); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_in_plaintext_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"{}":{{"$in":["{}"]}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::In(name1, vec![value1]); - - assert_eq!(query, expected); - } - - #[test] - fn test_simple_operator_in_plaintexts_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let value2 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"{}":{{"$in":["{}","{}","{}"]}}}}"#, - name1, value1, value2, value3 - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::In(name1, vec![value1, value2, value3]); - - assert_eq!(query, expected); - } - - #[test] - fn test_exist_parse_string() { - let name1 = _random_string(10); - - let json = format!(r#"{{"$exist":"{}"}}"#, name1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Exist(vec![name1]); - - assert_eq!(query, expected); - } - - #[test] - fn test_exist_parse_array() { - let name1 = _random_string(10); - let name2 = _random_string(10); - - let json = format!(r#"{{"$exist":["{}","{}"]}}"#, name1, name2); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Exist(vec![name1, name2]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_exist() { - let name1 = _random_string(10); - let name2 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"$exist":"{}"}},{{"$exist":"{}"}}]}}"#, - name1, name2 - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Exist(vec![name1]), Query::Exist(vec![name2])]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":"{}"}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Eq(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Neq(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Gt(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Gte(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Lt(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_lte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Lte(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Like(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_in_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::In(name1, vec![value1])]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_one_not_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$and":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![Query::Not(Box::new(Query::Eq(name1, value1)))]); - - assert_eq!(query, expected); - } - - #[test] - fn test_short_and_with_multiple_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"{}":"{}","{}":"{}","{}":"{}"}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - let mut clauses = vec![ - Query::Eq(name1, value1), - Query::Eq(name2, value2), - Query::Eq(name3, value3), - ]; - clauses.sort(); - - let expected = Query::And(clauses); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Eq(name1, value1), - Query::Eq(name2, value2), - Query::Eq(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Neq(name1, value1), - Query::Neq(name2, value2), - Query::Neq(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Gt(name1, value1), - Query::Gt(name2, value2), - Query::Gt(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Gte(name1, value1), - Query::Gte(name2, value2), - Query::Gte(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Lt(name1, value1), - Query::Lt(name2, value2), - Query::Lt(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_lte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Lte(name1, value1), - Query::Lte(name2, value2), - Query::Lte(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Like(name1, value1), - Query::Like(name2, value2), - Query::Like(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_in_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::In(name1, vec![value1]), - Query::In(name2, vec![value2]), - Query::In(name3, vec![value3]), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_not_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Not(Box::new(Query::Eq(name1, value1))), - Query::Not(Box::new(Query::Eq(name2, value2))), - Query::Not(Box::new(Query::Eq(name3, value3))), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_with_multiple_mixed_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8a = _random_string(10); - let value8b = _random_string(10); - let name9 = _random_string(10); - let value9 = _random_string(10); - - let json = format!( - r#"{{"$and":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8a, - value8b, - name9, - value9, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![ - Query::Eq(name1, value1), - Query::Neq(name2, value2), - Query::Gt(name3, value3), - Query::Gte(name4, value4), - Query::Lt(name5, value5), - Query::Lte(name6, value6), - Query::Like(name7, value7), - Query::In(name8, vec![value8a, value8b]), - Query::Not(Box::new(Query::Eq(name9, value9))), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":"{}"}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Eq(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Neq(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Gt(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Gte(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Lt(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_lte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Lte(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Like(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_in_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::In(name1, vec![value1])]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_one_not_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$or":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Not(Box::new(Query::Eq(name1, value1)))]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Eq(name1, value1), - Query::Eq(name2, value2), - Query::Eq(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Neq(name1, value1), - Query::Neq(name2, value2), - Query::Neq(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Gt(name1, value1), - Query::Gt(name2, value2), - Query::Gt(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Gte(name1, value1), - Query::Gte(name2, value2), - Query::Gte(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Lt(name1, value1), - Query::Lt(name2, value2), - Query::Lt(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_lte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Lte(name1, value1), - Query::Lte(name2, value2), - Query::Lte(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Like(name1, value1), - Query::Like(name2, value2), - Query::Like(name3, value3), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_in_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::In(name1, vec![value1]), - Query::In(name2, vec![value2]), - Query::In(name3, vec![value3]), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_not_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Not(Box::new(Query::Eq(name1, value1))), - Query::Not(Box::new(Query::Eq(name2, value2))), - Query::Not(Box::new(Query::Eq(name3, value3))), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_or_with_multiple_mixed_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8a = _random_string(10); - let value8b = _random_string(10); - let name9 = _random_string(10); - let value9 = _random_string(10); - - let json = format!( - r#"{{"$or":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8a, - value8b, - name9, - value9, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![ - Query::Eq(name1, value1), - Query::Neq(name2, value2), - Query::Gt(name3, value3), - Query::Gte(name4, value4), - Query::Lt(name5, value5), - Query::Lte(name6, value6), - Query::Like(name7, value7), - Query::In(name8, vec![value8a, value8b]), - Query::Not(Box::new(Query::Eq(name9, value9))), - ]); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_eq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":"{}"}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Eq(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_neq_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$neq":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Neq(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_gt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$gt":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Gt(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_gte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$gte":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Gte(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_lt_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$lt":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Lt(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_lte_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$lte":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Lte(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_like_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$like":"{}"}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::Like(name1, value1))); - - assert_eq!(query, expected); - } - - #[test] - fn test_not_with_one_in_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let json = format!(r#"{{"$not":{{"{}":{{"$in":["{}"]}}}}}}"#, name1, value1); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::In(name1, vec![value1]))); - - assert_eq!(query, expected); - } - - #[test] - fn test_and_or_not_complex_case_parse() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8 = _random_string(10); - - let json = format!( - r#"{{"$not":{{"$and":[{{"{}":"{}"}},{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"$not":{{"{}":{{"$lte":"{}"}}}}}},{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"$not":{{"{}":{{"$gte":"{}"}}}}}}]}}]}},{{"$not":{{"{}":{{"$like":"{}"}}}}}},{{"$and":[{{"{}":"{}"}},{{"$not":{{"{}":{{"$neq":"{}"}}}}}}]}}]}}}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8, - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Not(Box::new(Query::And(vec![ - Query::Eq(name1, value1), - Query::Or(vec![ - Query::Gt(name2, value2), - Query::Not(Box::new(Query::Lte(name3, value3))), - Query::And(vec![ - Query::Lt(name4, value4), - Query::Not(Box::new(Query::Gte(name5, value5))), - ]), - ]), - Query::Not(Box::new(Query::Like(name6, value6))), - Query::And(vec![ - Query::Eq(name7, value7), - Query::Not(Box::new(Query::Neq(name8, value8))), - ]), - ]))); - - assert_eq!(query, expected); - } - - /// to string - #[test] - fn test_simple_operator_empty_and_to_string() { - let query = Query::And(vec![]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = "{}"; - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_empty_or_to_string() { - let query = Query::Or(vec![]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = "{}"; - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_empty_not_to_string() { - let query = Query::Not(Box::new(Query::And(vec![]))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = r#"{"$not":{}}"#; - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Eq(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":"{}"}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Neq(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$neq":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_gt_plaintext_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Gt(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$gt":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Gte(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$gte":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Lt(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$lt":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Lte(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$lte":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Like(name1.clone(), value1.clone()); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$like":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::In(name1.clone(), vec![value1.clone()]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"{}":{{"$in":["{}"]}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_simple_operator_in_multimply_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let value2 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::In( - name1.clone(), - vec![value1.clone(), value2.clone(), value3.clone()], - ); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"{}":{{"$in":["{}","{}","{}"]}}}}"#, - name1, value1, value2, value3 - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Eq(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":"{}"}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Neq(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_gt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Gt(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Gte(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Lt(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Lte(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Like(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::In(name1.clone(), vec![value1.clone()])]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_one_not_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::And(vec![Query::Not(Box::new(Query::Eq( - name1.clone(), - value1.clone(), - )))]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$and":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Eq(name1.clone(), value1.clone()), - Query::Eq(name2.clone(), value2.clone()), - Query::Eq(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Neq(name1.clone(), value1.clone()), - Query::Neq(name2.clone(), value2.clone()), - Query::Neq(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_gt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Gt(name1.clone(), value1.clone()), - Query::Gt(name2.clone(), value2.clone()), - Query::Gt(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Gte(name1.clone(), value1.clone()), - Query::Gte(name2.clone(), value2.clone()), - Query::Gte(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Lt(name1.clone(), value1.clone()), - Query::Lt(name2.clone(), value2.clone()), - Query::Lt(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Lte(name1.clone(), value1.clone()), - Query::Lte(name2.clone(), value2.clone()), - Query::Lte(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Like(name1.clone(), value1.clone()), - Query::Like(name2.clone(), value2.clone()), - Query::Like(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::In(name1.clone(), vec![value1.clone()]), - Query::In(name2.clone(), vec![value2.clone()]), - Query::In(name3.clone(), vec![value3.clone()]), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_not_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::And(vec![ - Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))), - Query::Not(Box::new(Query::Eq(name2.clone(), value2.clone()))), - Query::Not(Box::new(Query::Eq(name3.clone(), value3.clone()))), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_with_multiple_mixed_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8a = _random_string(10); - let value8b = _random_string(10); - let name9 = _random_string(10); - let value9 = _random_string(10); - - let query = Query::And(vec![ - Query::Eq(name1.clone(), value1.clone()), - Query::Neq(name2.clone(), value2.clone()), - Query::Gt(name3.clone(), value3.clone()), - Query::Gte(name4.clone(), value4.clone()), - Query::Lt(name5.clone(), value5.clone()), - Query::Lte(name6.clone(), value6.clone()), - Query::Like(name7.clone(), value7.clone()), - Query::In(name8.clone(), vec![value8a.clone(), value8b.clone()]), - Query::Not(Box::new(Query::Eq(name9.clone(), value9.clone()))), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$and":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8a, - value8b, - name9, - value9, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Eq(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":"{}"}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Neq(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_gt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Gt(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}}]}}"#, name1, value1); - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Gte(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Lt(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Lte(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Like(name1.clone(), value1.clone())]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$like":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::In(name1.clone(), vec![value1.clone()])]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_one_not_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Or(vec![Query::Not(Box::new(Query::Eq( - name1.clone(), - value1.clone(), - )))]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$or":[{{"$not":{{"{}":"{}"}}}}]}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Eq(name1.clone(), value1.clone()), - Query::Eq(name2.clone(), value2.clone()), - Query::Eq(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":"{}"}},{{"{}":"{}"}},{{"{}":"{}"}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Neq(name1.clone(), value1.clone()), - Query::Neq(name2.clone(), value2.clone()), - Query::Neq(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$neq":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_gt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Gt(name1.clone(), value1.clone()), - Query::Gt(name2.clone(), value2.clone()), - Query::Gt(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Gte(name1.clone(), value1.clone()), - Query::Gte(name2.clone(), value2.clone()), - Query::Gte(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$gte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Lt(name1.clone(), value1.clone()), - Query::Lt(name2.clone(), value2.clone()), - Query::Lt(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lt":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Lte(name1.clone(), value1.clone()), - Query::Lte(name2.clone(), value2.clone()), - Query::Lte(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$lte":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Like(name1.clone(), value1.clone()), - Query::Like(name2.clone(), value2.clone()), - Query::Like(name3.clone(), value3.clone()), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$like":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::In(name1.clone(), vec![value1.clone()]), - Query::In(name2.clone(), vec![value2.clone()]), - Query::In(name3.clone(), vec![value3.clone()]), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}},{{"{}":{{"$in":["{}"]}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_not_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - - let query = Query::Or(vec![ - Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))), - Query::Not(Box::new(Query::Eq(name2.clone(), value2.clone()))), - Query::Not(Box::new(Query::Eq(name3.clone(), value3.clone()))), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, value1, name2, value2, name3, value3, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_or_with_multiple_mixed_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8a = _random_string(10); - let value8b = _random_string(10); - let name9 = _random_string(10); - let value9 = _random_string(10); - - let query = Query::Or(vec![ - Query::Eq(name1.clone(), value1.clone()), - Query::Neq(name2.clone(), value2.clone()), - Query::Gt(name3.clone(), value3.clone()), - Query::Gte(name4.clone(), value4.clone()), - Query::Lt(name5.clone(), value5.clone()), - Query::Lte(name6.clone(), value6.clone()), - Query::Like(name7.clone(), value7.clone()), - Query::In(name8.clone(), vec![value8a.clone(), value8b.clone()]), - Query::Not(Box::new(Query::Eq(name9.clone(), value9.clone()))), - ]); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$or":[{{"{}":"{}"}},{{"{}":{{"$neq":"{}"}}}},{{"{}":{{"$gt":"{}"}}}},{{"{}":{{"$gte":"{}"}}}},{{"{}":{{"$lt":"{}"}}}},{{"{}":{{"$lte":"{}"}}}},{{"{}":{{"$like":"{}"}}}},{{"{}":{{"$in":["{}","{}"]}}}},{{"$not":{{"{}":"{}"}}}}]}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8a, - value8b, - name9, - value9, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_eq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Eq(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":"{}"}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_neq_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Neq(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$neq":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_gt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Gt(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$gt":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_gte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Gte(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$gte":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_lt_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Lt(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$lt":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_lte_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Lte(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$lte":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_like_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::Like(name1.clone(), value1.clone()))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$like":"{}"}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_not_with_one_in_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - - let query = Query::Not(Box::new(Query::In(name1.clone(), vec![value1.clone()]))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!(r#"{{"$not":{{"{}":{{"$in":["{}"]}}}}}}"#, name1, value1); - - assert_eq!(json, expected); - } - - #[test] - fn test_and_or_not_complex_case_to_string() { - let name1 = _random_string(10); - let value1 = _random_string(10); - let name2 = _random_string(10); - let value2 = _random_string(10); - let name3 = _random_string(10); - let value3 = _random_string(10); - let name4 = _random_string(10); - let value4 = _random_string(10); - let name5 = _random_string(10); - let value5 = _random_string(10); - let name6 = _random_string(10); - let value6 = _random_string(10); - let name7 = _random_string(10); - let value7 = _random_string(10); - let name8 = _random_string(10); - let value8 = _random_string(10); - - let query = Query::Not(Box::new(Query::And(vec![ - Query::Eq(name1.clone(), value1.clone()), - Query::Or(vec![ - Query::Gt(name2.clone(), value2.clone()), - Query::Not(Box::new(Query::Lte(name3.clone(), value3.clone()))), - Query::And(vec![ - Query::Lt(name4.clone(), value4.clone()), - Query::Not(Box::new(Query::Gte(name5.clone(), value5.clone()))), - ]), - ]), - Query::Not(Box::new(Query::Like(name6.clone(), value6.clone()))), - Query::And(vec![ - Query::Eq(name7.clone(), value7.clone()), - Query::Not(Box::new(Query::Neq(name8.clone(), value8.clone()))), - ]), - ]))); - - let json = ::serde_json::to_string(&query).unwrap(); - - let expected = format!( - r#"{{"$not":{{"$and":[{{"{}":"{}"}},{{"$or":[{{"{}":{{"$gt":"{}"}}}},{{"$not":{{"{}":{{"$lte":"{}"}}}}}},{{"$and":[{{"{}":{{"$lt":"{}"}}}},{{"$not":{{"{}":{{"$gte":"{}"}}}}}}]}}]}},{{"$not":{{"{}":{{"$like":"{}"}}}}}},{{"$and":[{{"{}":"{}"}},{{"$not":{{"{}":{{"$neq":"{}"}}}}}}]}}]}}}}"#, - name1, - value1, - name2, - value2, - name3, - value3, - name4, - value4, - name5, - value5, - name6, - value6, - name7, - value7, - name8, - value8, - ); - - assert_eq!(json, expected); - } - - #[test] - fn test_old_format() { - let name1 = _random_string(10); - let name2 = _random_string(10); - let value1 = _random_string(10); - let value2 = _random_string(10); - - let json = format!( - r#"[{{"{}":"{}"}}, {{"{}":"{}"}}]"#, - name1, value1, name2, value2 - ); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Eq(name1, value1), Query::Eq(name2, value2)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_old_format_empty() { - let json = format!(r#"[]"#); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::And(vec![]); - - assert_eq!(query, expected); - } - - #[test] - fn test_old_format_with_nulls() { - let name1 = _random_string(10); - let name2 = _random_string(10); - let value1 = _random_string(10); - - let json = json!(vec![ - json ! ({name1.clone(): value1.clone()}), - json!({ name2.clone(): serde_json::Value::Null }) - ]) - .to_string(); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - let expected = Query::Or(vec![Query::Eq(name1, value1)]); - - assert_eq!(query, expected); - } - - #[test] - fn test_optimise_and() { - let json = r#"{}"#; - - let query: Query = ::serde_json::from_str(json).unwrap(); - - assert_eq!(query.optimise(), None); - } - - #[test] - fn test_optimise_or() { - let json = r#"[]"#; - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - assert_eq!(query.optimise(), None); - } - - #[test] - fn test_optimise_single_nested_and() { - let json = json!({ - "$and": [ - { - "$and": [] - } - ] - }) - .to_string(); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - assert_eq!(query.optimise(), None); - } - - #[test] - fn test_optimise_several_nested_and() { - let json = json!({ - "$and": [ - { - "$and": [] - }, - { - "$and": [] - } - ] - }) - .to_string(); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - assert_eq!(query.optimise(), None); - } - - #[test] - fn test_optimise_single_nested_or() { - let json = json!({ - "$and": [ - { - "$or": [] - } - ] - }) - .to_string(); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - assert_eq!(query.optimise(), None); - } - - #[test] - fn test_optimise_several_nested_or() { - let json = json!({ - "$and": [ - { - "$or": [] - }, - { - "$or": [] - } - ] - }) - .to_string(); - - let query: Query = ::serde_json::from_str(&json).unwrap(); - - assert_eq!(query.optimise(), None); - } -} From 2571728226bec586baa152178f6e9fb8eefa6f81 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 29 Apr 2021 09:23:24 -0700 Subject: [PATCH 3/5] update to newer indy-utils, sha2 versions Signed-off-by: Andrew Whitehead --- indy-credx/Cargo.toml | 7 ++++--- indy-credx/src/services/tails.rs | 12 ++++++------ indy-data-types/Cargo.toml | 17 +++++++++-------- indy-data-types/src/anoncreds/cred_def.rs | 9 ++++----- indy-data-types/src/anoncreds/credential.rs | 7 +++++-- indy-data-types/src/anoncreds/master_secret.rs | 2 +- indy-data-types/src/anoncreds/nonce.rs | 4 ++-- indy-data-types/src/lib.rs | 6 ++---- indy-data-types/src/merkle_tree/merkletree.rs | 6 +++--- indy-data-types/src/merkle_tree/mod.rs | 12 +++++++----- indy-data-types/src/merkle_tree/proof.rs | 4 ++-- indy-data-types/src/merkle_tree/tree.rs | 3 ++- indy-wql/Cargo.toml | 2 +- 13 files changed, 48 insertions(+), 43 deletions(-) diff --git a/indy-credx/Cargo.toml b/indy-credx/Cargo.toml index b08b864..bb6bdf2 100644 --- a/indy-credx/Cargo.toml +++ b/indy-credx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "indy-credx" -version = "0.2.3" +version = "0.3.0" authors = ["Hyperledger Indy Contributors "] description = "Verifiable credential issuance and presentation for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." edition = "2018" @@ -30,17 +30,18 @@ rand = "0.7" regex = "1.2.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +sha2 = "0.9" tempfile = "3.1.0" thiserror = "1.0.9" zeroize = { version = "1.1", optional = true } [dependencies.indy-data-types] -version = "0.4" +version = "0.5" path = "../indy-data-types" features = ["cl_native"] [dependencies.indy-utils] -version = "0.3" +version = "0.4" path = "../indy-utils" default-features = false features = ["wql"] diff --git a/indy-credx/src/services/tails.rs b/indy-credx/src/services/tails.rs index e928ba1..8c3ba28 100644 --- a/indy-credx/src/services/tails.rs +++ b/indy-credx/src/services/tails.rs @@ -4,13 +4,13 @@ use std::io::{Read, Seek, SeekFrom, Write}; use std::path::PathBuf; use indy_utils::base58; +use sha2::{Digest, Sha256}; use tempfile; use crate::error::Result; use crate::ursa::{ cl::{RevocationTailsAccessor, RevocationTailsGenerator, Tail}, errors::{UrsaCryptoError, UrsaCryptoErrorKind}, - hash::{sha2::Sha256, Digest}, }; const TAILS_BLOB_TAG_SZ: u8 = 2; @@ -110,10 +110,10 @@ impl TailsReaderImpl for TailsFileReader { loop { let sz = file.read(&mut buf)?; if sz == 0 { - self.hash = Some(hasher.result().to_vec()); + self.hash = Some(hasher.finalize().to_vec()); return Ok(self.hash.as_ref().unwrap().clone()); } - hasher.input(&buf[0..sz]); + hasher.update(&buf[0..sz]); } } @@ -155,14 +155,14 @@ impl TailsWriter for TailsFileWriter { let mut hasher = Sha256::default(); let version = &[0u8, 2u8]; file.write(version)?; - hasher.input(version); + hasher.update(version); while let Some(tail) = generator.try_next()? { let tail_bytes = tail.to_bytes()?; file.write(tail_bytes.as_slice())?; - hasher.input(tail_bytes); + hasher.update(tail_bytes); } let tails_size = &file.seek(SeekFrom::Current(0))?; - let hash = base58::encode(hasher.result()); + let hash = base58::encode(hasher.finalize()); let path = tempf.path().with_file_name(hash.clone()); let _outf = match tempf.persist_noclobber(&path) { Ok(f) => f, diff --git a/indy-data-types/Cargo.toml b/indy-data-types/Cargo.toml index 7f5a58e..75d9c13 100644 --- a/indy-data-types/Cargo.toml +++ b/indy-data-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "indy-data-types" -version = "0.4.2" +version = "0.5.0" authors = ["Hyperledger Indy Contributors "] description = "Common data types for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." edition = "2018" @@ -17,24 +17,25 @@ crate-type = ["rlib"] [features] default = ["merkle_tree", "serde_support"] -cl = ["indy-utils/cl", "serde_support"] -cl_native = ["indy-utils/cl_native", "serde_support"] -hash = ["indy-utils/hash"] -merkle_tree = ["hash"] +cl = ["serde_support", "ursa", "ursa/cl"] +cl_native = ["serde_support", "ursa", "ursa/cl_native"] +merkle_tree = ["indy-utils/hash", "hex"] rich_schema = [] -serde_support = ["indy-utils/serde_support", "serde", "serde_json"] +serde_support = ["indy-utils/serde", "serde", "serde_json"] vendored = ["openssl", "openssl/vendored"] [dependencies] +hex = { version = "0.4", optional = true } openssl = { version = "0.10", optional = true } once_cell = "1.4" regex = "1.3" serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true, features = ["raw_value"] } -zeroize = "1.1" +ursa = { version = "0.3.5", default-features = false, optional = true } +zeroize = { version = "1.1", features = ["zeroize_derive"] } [dependencies.indy-utils] -version = "0.3" +version = "0.4" path = "../indy-utils" default-features = false features = ["wql"] diff --git a/indy-data-types/src/anoncreds/cred_def.rs b/indy-data-types/src/anoncreds/cred_def.rs index ad8c183..69d1ba4 100644 --- a/indy-data-types/src/anoncreds/cred_def.rs +++ b/indy-data-types/src/anoncreds/cred_def.rs @@ -88,13 +88,12 @@ pub struct CredentialDefinitionV1 { #[cfg(any(feature = "cl", feature = "cl_native"))] impl CredentialDefinitionV1 { - pub fn get_public_key( - &self, - ) -> Result { + pub fn get_public_key(&self) -> Result { let key = crate::ursa::cl::CredentialPublicKey::build_from_parts( &self.value.primary, self.value.revocation.as_ref(), - )?; + ) + .map_err(|e| e.to_string())?; Ok(key) } } @@ -123,7 +122,7 @@ impl CredentialKeyCorrectnessProof { #[cfg(any(feature = "cl", feature = "cl_native"))] { Ok(Self { - value: self.value.try_clone()?, + value: self.value.try_clone().map_err(|e| e.to_string())?, }) } #[cfg(not(any(feature = "cl", feature = "cl_native")))] diff --git a/indy-data-types/src/anoncreds/credential.rs b/indy-data-types/src/anoncreds/credential.rs index 4046b48..b180f31 100644 --- a/indy-data-types/src/anoncreds/credential.rs +++ b/indy-data-types/src/anoncreds/credential.rs @@ -28,8 +28,11 @@ impl Credential { cred_def_id: self.cred_def_id.clone(), rev_reg_id: self.rev_reg_id.clone(), values: self.values.clone(), - signature: self.signature.try_clone()?, - signature_correctness_proof: self.signature_correctness_proof.try_clone()?, + signature: self.signature.try_clone().map_err(|e| e.to_string())?, + signature_correctness_proof: self + .signature_correctness_proof + .try_clone() + .map_err(|e| e.to_string())?, rev_reg: self.rev_reg.clone(), witness: self.witness.clone(), }) diff --git a/indy-data-types/src/anoncreds/master_secret.rs b/indy-data-types/src/anoncreds/master_secret.rs index 58fce5e..1d5a648 100644 --- a/indy-data-types/src/anoncreds/master_secret.rs +++ b/indy-data-types/src/anoncreds/master_secret.rs @@ -22,7 +22,7 @@ impl MasterSecret { pub fn try_clone(&self) -> Result { Ok(Self { - value: self.value.try_clone()?, + value: self.value.try_clone().map_err(|e| e.to_string())?, }) } } diff --git a/indy-data-types/src/anoncreds/nonce.rs b/indy-data-types/src/anoncreds/nonce.rs index a2aa362..6efc0df 100644 --- a/indy-data-types/src/anoncreds/nonce.rs +++ b/indy-data-types/src/anoncreds/nonce.rs @@ -27,7 +27,7 @@ impl Nonce { #[cfg(any(feature = "cl", feature = "cl_native"))] #[inline] pub fn from_native(native: UrsaNonce) -> Result { - let strval = native.to_dec()?; + let strval = native.to_dec().map_err(|e| e.to_string())?; Ok(Self { strval, native }) } @@ -55,7 +55,7 @@ impl Nonce { } #[cfg(any(feature = "cl", feature = "cl_native"))] { - let native = UrsaNonce::from_dec(&strval)?; + let native = UrsaNonce::from_dec(&strval).map_err(|e| e.to_string())?; Ok(Self { strval, native }) } #[cfg(not(any(feature = "cl", feature = "cl_native")))] diff --git a/indy-data-types/src/lib.rs b/indy-data-types/src/lib.rs index 08334aa..f993780 100644 --- a/indy-data-types/src/lib.rs +++ b/indy-data-types/src/lib.rs @@ -11,8 +11,6 @@ mod macros; mod utils { pub use indy_utils::base58; - #[cfg(feature = "hash")] - pub use indy_utils::hash; pub use indy_utils::{qualifiable, Qualifiable}; } @@ -20,8 +18,8 @@ pub use indy_utils::did; pub use indy_utils::keys; pub use indy_utils::{invalid, ConversionError, Validatable, ValidationError}; -#[cfg(any(feature = "cl", feature = "cl_native", feature = "hash"))] -pub use indy_utils::ursa; +#[cfg(any(feature = "cl", feature = "cl_native"))] +pub use ursa; /// Type definitions related Indy credential issuance and verification pub mod anoncreds; diff --git a/indy-data-types/src/merkle_tree/merkletree.rs b/indy-data-types/src/merkle_tree/merkletree.rs index 9ea9f62..da89d4b 100644 --- a/indy-data-types/src/merkle_tree/merkletree.rs +++ b/indy-data-types/src/merkle_tree/merkletree.rs @@ -1,11 +1,11 @@ -use crate::utils::hash::{ +use indy_utils::hash::{ TreeHash, SHA256::{digest_empty, DigestType as Hash}, }; -use crate::ValidationError; use super::proof::{Lemma, Proof}; use super::tree::{LeavesIntoIterator, LeavesIterator, Tree, TreeLeafData}; +use crate::ValidationError; /// A Merkle tree is a binary tree, with values of type `T` at the leafs, /// and where every internal node holds the hash of the concatenation of the hashes of its children nodes. @@ -102,7 +102,7 @@ impl MerkleTree { /// Returns the hex root hash of Merkle tree pub fn root_hash_hex(&self) -> String { - indy_utils::hex::encode(self.root.hash()) + hex::encode(self.root.hash()) } /// Returns the height of Merkle tree diff --git a/indy-data-types/src/merkle_tree/mod.rs b/indy-data-types/src/merkle_tree/mod.rs index 88966fa..44fde87 100644 --- a/indy-data-types/src/merkle_tree/mod.rs +++ b/indy-data-types/src/merkle_tree/mod.rs @@ -1,12 +1,14 @@ -mod merkletree; -mod proof; -mod tree; +use indy_utils::hash::{TreeHash, SHA256::DigestType as Hash}; -pub use self::merkletree::MerkleTree; use self::tree::{Tree, TreeLeafData}; -use crate::utils::hash::{TreeHash, SHA256::DigestType as Hash}; use crate::ValidationError; +mod merkletree; +pub use self::merkletree::MerkleTree; + +mod proof; +mod tree; + impl MerkleTree { fn count_bits(v: usize) -> usize { let mut ret = 0; diff --git a/indy-data-types/src/merkle_tree/proof.rs b/indy-data-types/src/merkle_tree/proof.rs index c7d72a7..ed798f9 100644 --- a/indy-data-types/src/merkle_tree/proof.rs +++ b/indy-data-types/src/merkle_tree/proof.rs @@ -1,7 +1,7 @@ -use crate::utils::hash::{TreeHash, SHA256::DigestType as Hash}; -use crate::ValidationError; +use indy_utils::hash::{TreeHash, SHA256::DigestType as Hash}; use super::tree::{Tree, TreeLeafData}; +use crate::ValidationError; /// An inclusion proof represent the fact that a `value` is a member /// of a `MerkleTree` with root hash `root_hash`. diff --git a/indy-data-types/src/merkle_tree/tree.rs b/indy-data-types/src/merkle_tree/tree.rs index e8a96c8..551aa7d 100644 --- a/indy-data-types/src/merkle_tree/tree.rs +++ b/indy-data-types/src/merkle_tree/tree.rs @@ -1,6 +1,7 @@ use std::cmp; -use crate::utils::hash::{TreeHash, SHA256::DigestType as Hash}; +use indy_utils::hash::{TreeHash, SHA256::DigestType as Hash}; + use crate::ValidationError; pub type TreeLeafData = Vec; diff --git a/indy-wql/Cargo.toml b/indy-wql/Cargo.toml index aec381e..c40ba40 100644 --- a/indy-wql/Cargo.toml +++ b/indy-wql/Cargo.toml @@ -2,7 +2,7 @@ name = "indy-wql" version = "0.4.0" authors = ["Hyperledger Indy Contributors "] -description = "Utilities for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." +description = "Wallet Query Language for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org)." edition = "2018" license = "Apache-2.0" readme = "../README.md" From acc689440240c5b5a31e8075943782d3628249b7 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 29 Apr 2021 09:36:56 -0700 Subject: [PATCH 4/5] update formatting Signed-off-by: Andrew Whitehead --- indy-utils/src/error.rs | 41 +++++++++++++++++++++++++++-------------- indy-utils/src/hash.rs | 2 +- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/indy-utils/src/error.rs b/indy-utils/src/error.rs index 73af47b..23c1f38 100644 --- a/indy-utils/src/error.rs +++ b/indy-utils/src/error.rs @@ -18,50 +18,64 @@ macro_rules! define_error { } pub fn from_err(err: E) -> Self - where E: StdError + Send + Sync + 'static { + where + E: StdError + Send + Sync + 'static, + { Self { context: None, - source: Some(Box::new(err) as DynError) + source: Some(Box::new(err) as DynError), } } pub fn from_msg_err(msg: M, err: E) -> Self - where M: Into, E: StdError + Send + Sync + 'static - { + where + M: Into, + E: StdError + Send + Sync + 'static, + { Self { context: Some(msg.into()), - source: Some(Box::new(err) as DynError) + source: Some(Box::new(err) as DynError), } } } impl From<&str> for $name { fn from(context: &str) -> Self { - Self { context: Some(context.to_owned()), source: None } + Self { + context: Some(context.to_owned()), + source: None, + } } } impl From for $name { fn from(context: String) -> Self { - Self { context: Some(context), source: None } + Self { + context: Some(context), + source: None, + } } } impl From> for $name { fn from(context: Option) -> Self { - Self { context, source: None } + Self { + context, + source: None, + } } } impl From<(M, E)> for $name - where M: Into, - E: StdError + Send + Sync + 'static { + where + M: Into, + E: StdError + Send + Sync + 'static, + { fn from((context, err): (M, E)) -> Self { Self::from_msg_err(context, err) } } - impl Into for $name { fn into(self) -> String { self.to_string() @@ -72,9 +86,8 @@ macro_rules! define_error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, $short)?; match self.context { - Some(ref context) => - write!(f, ": {}", context), - None => Ok(()) + Some(ref context) => write!(f, ": {}", context), + None => Ok(()), } } } diff --git a/indy-utils/src/hash.rs b/indy-utils/src/hash.rs index 76da166..e162a41 100644 --- a/indy-utils/src/hash.rs +++ b/indy-utils/src/hash.rs @@ -27,7 +27,7 @@ macro_rules! hash_type { DigestType::output_size() } } - } + }; } hash_type!(SHA256, sha2::Sha256, "Sha256 hash"); From 2be0b1aba9b80ed37da75313900d16c0928ad89e Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 29 Apr 2021 09:53:39 -0700 Subject: [PATCH 5/5] update feature flags Signed-off-by: Andrew Whitehead --- indy-credx/Cargo.toml | 5 ----- indy-credx/src/error.rs | 2 +- indy-credx/src/services/helpers.rs | 19 +++++++++---------- indy-data-types/Cargo.toml | 6 +++--- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/indy-credx/Cargo.toml b/indy-credx/Cargo.toml index bb6bdf2..0a56b00 100644 --- a/indy-credx/Cargo.toml +++ b/indy-credx/Cargo.toml @@ -45,8 +45,3 @@ version = "0.4" path = "../indy-utils" default-features = false features = ["wql"] - -[dependencies.ursa] -version = "0.3.5" -default-features = false -features = ["cl_native", "log", "serde"] diff --git a/indy-credx/src/error.rs b/indy-credx/src/error.rs index 6a40324..0b6361d 100644 --- a/indy-credx/src/error.rs +++ b/indy-credx/src/error.rs @@ -2,7 +2,7 @@ use std::error::Error as StdError; use std::fmt::{self, Display, Formatter}; use std::result::Result as StdResult; -use ursa::errors::{UrsaCryptoError, UrsaCryptoErrorKind}; +use crate::ursa::errors::{UrsaCryptoError, UrsaCryptoErrorKind}; pub type Result = std::result::Result; diff --git a/indy-credx/src/services/helpers.rs b/indy-credx/src/services/helpers.rs index cc22345..661d21f 100644 --- a/indy-credx/src/services/helpers.rs +++ b/indy-credx/src/services/helpers.rs @@ -1,12 +1,4 @@ -use ursa::{ - bn::BigNumber, - cl::{ - issuer, verifier, CredentialSchema, CredentialValues as CryptoCredentialValues, - MasterSecret as CryptoMasterSecret, NonCredentialSchema, SubProofRequest, - }, -}; - -use crate::error::Result; +use std::collections::{HashMap, HashSet}; use indy_data_types::anoncreds::{ credential::AttributeValues, @@ -15,7 +7,14 @@ use indy_data_types::anoncreds::{ }; use indy_utils::hash::SHA256; -use std::collections::{HashMap, HashSet}; +use crate::error::Result; +use crate::ursa::{ + bn::BigNumber, + cl::{ + issuer, verifier, CredentialSchema, CredentialValues as CryptoCredentialValues, + MasterSecret as CryptoMasterSecret, NonCredentialSchema, SubProofRequest, + }, +}; pub fn attr_common_view(attr: &str) -> String { attr.replace(" ", "").to_lowercase() diff --git a/indy-data-types/Cargo.toml b/indy-data-types/Cargo.toml index 75d9c13..7cba54a 100644 --- a/indy-data-types/Cargo.toml +++ b/indy-data-types/Cargo.toml @@ -17,11 +17,11 @@ crate-type = ["rlib"] [features] default = ["merkle_tree", "serde_support"] -cl = ["serde_support", "ursa", "ursa/cl"] -cl_native = ["serde_support", "ursa", "ursa/cl_native"] +cl = ["serde_support", "ursa", "ursa/cl", "ursa/serde"] +cl_native = ["serde_support", "ursa", "ursa/cl_native", "ursa/serde"] merkle_tree = ["indy-utils/hash", "hex"] rich_schema = [] -serde_support = ["indy-utils/serde", "serde", "serde_json"] +serde_support = ["serde", "serde_json"] vendored = ["openssl", "openssl/vendored"] [dependencies]