pub trait GraphQLFields {
type FullType;
fn selection() -> String;
}
impl<T: GraphQLFields> GraphQLFields for Option<T> {
type FullType = T::FullType;
fn selection() -> String {
T::selection()
}
}
impl<T: GraphQLFields> GraphQLFields for Vec<T> {
type FullType = T::FullType;
fn selection() -> String {
T::selection()
}
}
pub trait FieldCompatible<Custom> {}
impl<T> FieldCompatible<T> for T {}
impl<T> FieldCompatible<T> for Option<T> {}
impl<T> FieldCompatible<T> for Option<Box<T>> {}
impl<T> FieldCompatible<Option<T>> for Option<Box<T>> {}
impl FieldCompatible<String> for chrono::DateTime<chrono::Utc> {}
impl FieldCompatible<Option<String>> for Option<chrono::DateTime<chrono::Utc>> {}
impl FieldCompatible<String> for Option<chrono::DateTime<chrono::Utc>> {}
#[cfg(test)]
mod tests {
use super::*;
struct FakeFullType;
struct FakeIssue;
impl GraphQLFields for FakeIssue {
type FullType = FakeFullType;
fn selection() -> String {
"id title url".to_string()
}
}
#[test]
fn option_delegates_selection_to_inner_type() {
assert_eq!(
<Option<FakeIssue> as GraphQLFields>::selection(),
"id title url"
);
}
#[test]
fn vec_delegates_selection_to_inner_type() {
assert_eq!(
<Vec<FakeIssue> as GraphQLFields>::selection(),
"id title url"
);
}
#[test]
fn option_preserves_full_type() {
fn assert_full_type<T: GraphQLFields<FullType = FakeFullType>>() {}
assert_full_type::<FakeIssue>();
assert_full_type::<Option<FakeIssue>>();
assert_full_type::<Vec<FakeIssue>>();
}
#[test]
fn option_nullable_query_deserialization() {
#[derive(serde::Deserialize)]
struct MyIssue {
id: String,
}
impl GraphQLFields for MyIssue {
type FullType = FakeFullType;
fn selection() -> String {
"id".to_string()
}
}
let null_val = serde_json::Value::Null;
let result: Option<MyIssue> = serde_json::from_value(null_val).unwrap();
assert!(result.is_none());
let obj_val = serde_json::json!({"id": "abc-123"});
let result: Option<MyIssue> = serde_json::from_value(obj_val).unwrap();
assert_eq!(result.unwrap().id, "abc-123");
assert_eq!(<Option<MyIssue> as GraphQLFields>::selection(), "id");
}
}