use crate::objects::common::PageInfo;
use serde::de::{self, Deserializer, MapAccess, Visitor};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use std::fmt;
use std::marker::PhantomData;
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphQLResponse<T> {
pub data: T,
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Page<T> {
pub page_info: Option<PageInfo>,
pub data: T,
}
impl<'de, T> Deserialize<'de> for Page<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PageVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for PageVisitor<T>
where
T: Deserialize<'de>,
{
type Value = Page<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an object with a 'pageInfo' field and one other data field")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut page_info = None;
let mut data = None;
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"pageInfo" => {
if page_info.is_some() {
return Err(de::Error::duplicate_field("pageInfo"));
}
page_info = Some(map.next_value()?);
}
"extensions" => {
let _ = map.next_value::<de::IgnoredAny>()?;
}
_ => {
if data.is_some() {
return Err(de::Error::custom("found more than one data field"));
}
data = Some(map.next_value()?);
}
}
}
let data = data.ok_or_else(|| de::Error::custom("missing data field"))?;
Ok(Page { page_info, data })
}
}
deserializer.deserialize_map(PageVisitor(PhantomData))
}
}
struct InnerData<T> {
data: T,
}
impl<'de, T> Deserialize<'de> for InnerData<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct InnerVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for InnerVisitor<T>
where
T: Deserialize<'de>,
{
type Value = InnerData<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an object with a single field containing an array")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
map.next_key::<de::IgnoredAny>()?.ok_or_else(|| {
de::Error::custom("expected a single data field, but the object was empty")
})?;
let data: T = map.next_value()?;
Ok(InnerData { data })
}
}
deserializer.deserialize_map(InnerVisitor(PhantomData))
}
}
impl<'de, T> Deserialize<'de> for GraphQLResponse<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct OuterVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for OuterVisitor<T>
where
T: Deserialize<'de>,
{
type Value = GraphQLResponse<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an object with a single 'data' field")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let key = map.next_key::<String>()?.ok_or_else(|| {
de::Error::custom("expected field 'data', but object was empty")
})?;
if key != "data" {
return Err(de::Error::invalid_value(
de::Unexpected::Str(&key),
&"the field 'data'",
));
}
let inner: InnerData<T> = map.next_value()?;
Ok(GraphQLResponse { data: inner.data })
}
}
deserializer.deserialize_map(OuterVisitor(PhantomData))
}
}