diff --git a/src/core/jit/exec.rs b/src/core/jit/exec.rs index bbc97a46c2..ae12be86ee 100644 --- a/src/core/jit/exec.rs +++ b/src/core/jit/exec.rs @@ -22,7 +22,7 @@ pub struct Executor { impl Executor where - Output: JsonLike + Debug, + Output: JsonLike + Debug, Synth: Synthesizer>, Exec: IRExecutor, { @@ -55,7 +55,7 @@ struct ExecutorInner<'a, Input, Output, Error, Exec> { impl<'a, Input, Output, Error, Exec> ExecutorInner<'a, Input, Output, Error, Exec> where - Output: JsonLike + Debug, + Output: JsonLike + Debug, Exec: IRExecutor, { fn new( diff --git a/src/core/json/json_like.rs b/src/core/json/json_like.rs index 479de04c45..a08a62a75c 100644 --- a/src/core/json/json_like.rs +++ b/src/core/json/json_like.rs @@ -2,9 +2,20 @@ use std::collections::HashMap; use async_graphql_value::ConstValue; +use crate::core::json::json_object_like::JsonObjectLike; + pub trait JsonLike { - type Output; - fn as_array_ok(&self) -> Result<&Vec, &str>; + type Json; + type JsonObject: JsonObjectLike; + + // Constructors + fn default() -> Self; + fn new_array(arr: Vec) -> Self; + fn new(value: &Self::Json) -> &Self; + + // Operators + fn as_array_ok(&self) -> Result<&Vec, &str>; + fn as_object_ok(&self) -> Result<&Self::JsonObject, &str>; fn as_str_ok(&self) -> Result<&str, &str>; fn as_string_ok(&self) -> Result<&String, &str>; fn as_i64_ok(&self) -> Result; @@ -12,16 +23,17 @@ pub trait JsonLike { fn as_f64_ok(&self) -> Result; fn as_bool_ok(&self) -> Result; fn as_null_ok(&self) -> Result<(), &str>; - fn as_option_ok(&self) -> Result, &str>; - fn get_path>(&self, path: &[T]) -> Option<&Self::Output>; - fn get_key(&self, path: &str) -> Option<&Self::Output>; - fn new(value: &Self::Output) -> &Self; - fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap>; + fn as_option_ok(&self) -> Result, &str>; + fn get_path>(&self, path: &[T]) -> Option<&Self::Json>; + fn get_key(&self, path: &str) -> Option<&Self::Json>; + fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap>; } impl JsonLike for serde_json::Value { - type Output = serde_json::Value; - fn as_array_ok(&self) -> Result<&Vec, &str> { + type Json = serde_json::Value; + type JsonObject = serde_json::Map; + + fn as_array_ok(&self) -> Result<&Vec, &str> { self.as_array().ok_or("expected array") } fn as_str_ok(&self) -> Result<&str, &str> { @@ -43,14 +55,14 @@ impl JsonLike for serde_json::Value { self.as_null().ok_or("expected null") } - fn as_option_ok(&self) -> Result, &str> { + fn as_option_ok(&self) -> Result, &str> { match self { serde_json::Value::Null => Ok(None), _ => Ok(Some(self)), } } - fn get_path>(&self, path: &[T]) -> Option<&Self::Output> { + fn get_path>(&self, path: &[T]) -> Option<&Self::Json> { let mut val = self; for token in path { val = match val { @@ -65,11 +77,11 @@ impl JsonLike for serde_json::Value { Some(val) } - fn new(value: &Self::Output) -> &Self { + fn new(value: &Self::Json) -> &Self { value } - fn get_key(&self, path: &str) -> Option<&Self::Output> { + fn get_key(&self, path: &str) -> Option<&Self::Json> { match self { serde_json::Value::Object(map) => map.get(path), _ => None, @@ -83,16 +95,32 @@ impl JsonLike for serde_json::Value { } } - fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap> { + fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap> { let src = gather_path_matches(self, path, vec![]); group_by_key(src) } + + fn default() -> Self { + Self::Null + } + + fn new_array(arr: Vec) -> Self { + Self::Array(arr) + } + + fn as_object_ok(&self) -> Result<&Self::JsonObject, &str> { + match self { + serde_json::Value::Object(map) => Ok(map), + _ => Err("expected object"), + } + } } impl JsonLike for async_graphql::Value { - type Output = async_graphql::Value; + type Json = async_graphql::Value; + type JsonObject = indexmap::IndexMap; - fn as_array_ok(&self) -> Result<&Vec, &str> { + fn as_array_ok(&self) -> Result<&Vec, &str> { match self { ConstValue::List(seq) => Ok(seq), _ => Err("array"), @@ -141,14 +169,14 @@ impl JsonLike for async_graphql::Value { } } - fn as_option_ok(&self) -> Result, &str> { + fn as_option_ok(&self) -> Result, &str> { match self { ConstValue::Null => Ok(None), _ => Ok(Some(self)), } } - fn get_path>(&self, path: &[T]) -> Option<&Self::Output> { + fn get_path>(&self, path: &[T]) -> Option<&Self::Json> { let mut val = self; for token in path { val = match val { @@ -163,11 +191,11 @@ impl JsonLike for async_graphql::Value { Some(val) } - fn new(value: &Self::Output) -> &Self { + fn new(value: &Self::Json) -> &Self { value } - fn get_key(&self, path: &str) -> Option<&Self::Output> { + fn get_key(&self, path: &str) -> Option<&Self::Json> { match self { ConstValue::Object(map) => map.get(&async_graphql::Name::new(path)), _ => None, @@ -180,10 +208,25 @@ impl JsonLike for async_graphql::Value { } } - fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap> { + fn group_by<'a>(&'a self, path: &'a [String]) -> HashMap> { let src = gather_path_matches(self, path, vec![]); group_by_key(src) } + + fn default() -> Self { + Default::default() + } + + fn new_array(arr: Vec) -> Self { + ConstValue::List(arr) + } + + fn as_object_ok(&self) -> Result<&Self::JsonObject, &str> { + match self { + ConstValue::Object(map) => Ok(map), + _ => Err("expected object"), + } + } } // Highly micro-optimized and benchmarked version of get_path_all diff --git a/src/core/json/json_object_like.rs b/src/core/json/json_object_like.rs new file mode 100644 index 0000000000..ac56101aea --- /dev/null +++ b/src/core/json/json_object_like.rs @@ -0,0 +1,26 @@ +use indexmap::IndexMap; + +use crate::core::json::JsonLike; + +pub trait JsonObjectLike { + type Value<'a>: JsonLike + where + Self: 'a; + fn get<'a>(&'a self, key: &'a str) -> Option<&Self::Value<'a>>; +} + +impl JsonObjectLike for serde_json::Map { + type Value<'a> = serde_json::Value; + + fn get<'a>(&'a self, key: &'a str) -> Option<&Self::Value<'a>> { + self.get(key) + } +} + +impl JsonObjectLike for IndexMap { + type Value<'a> = V where V: 'a; + + fn get<'a>(&'a self, key: &'a str) -> Option<&Self::Value<'a>> { + self.get(&async_graphql_value::Name::new(key)) + } +} diff --git a/src/core/json/mod.rs b/src/core/json/mod.rs index 19cf194ade..1205d15c4b 100644 --- a/src/core/json/mod.rs +++ b/src/core/json/mod.rs @@ -1,4 +1,7 @@ mod json_like; +mod json_object_like; mod json_schema; + pub use json_like::*; +pub use json_object_like::*; pub use json_schema::*;