use std::ops::Deref;
use log::trace;
use serde::{
de::{self, DeserializeOwned, Deserializer},
Deserialize,
};
use serde_json::value::Value;
use crate::{ArangoError, ClientError};
pub(crate) fn deserialize_response<T>(text: &str) -> Result<T, ClientError>
where
T: DeserializeOwned,
{
let response: Response<T> = serde_json::from_str(text)?;
Ok(Into::<Result<T, ArangoError>>::into(response)?)
}
#[derive(Debug)]
pub(crate) enum Response<T> {
Ok(T),
Err(ArangoError),
}
impl<T> From<Response<T>> for Result<T, ArangoError> {
fn from(resp: Response<T>) -> Self {
match resp {
Response::Ok(success) => Ok(success),
Response::Err(err) => Err(err),
}
}
}
impl<'de, T> Deserialize<'de> for Response<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let map = serde_json::Map::deserialize(deserializer)?;
trace!("Deserialize normal Response: {:?}", map);
let error = map
.get("error")
.map_or_else(|| Ok(false), Deserialize::deserialize)
.map_err(de::Error::custom)?;
let rest = Value::Object(map);
if error {
ArangoError::deserialize(rest)
.map(Response::Err)
.map_err(de::Error::custom)
} else {
T::deserialize(rest)
.map(Response::Ok)
.map_err(de::Error::custom)
}
}
}
#[derive(Deserialize, Debug)]
pub(crate) struct ArangoResult<T> {
#[serde(rename = "result")]
result: T,
}
impl<T> ArangoResult<T> {
pub fn unwrap(self) -> T {
self.result
}
}
impl<T> Deref for ArangoResult<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.result
}
}
#[cfg(test)]
mod test {
use super::*;
#[derive(Debug, Deserialize)]
pub struct CollectionResponse {
pub id: String,
pub name: String,
pub status: u8,
pub r#type: u8,
#[serde(rename = "isSystem")]
pub is_system: bool,
}
#[test]
fn response() {
let text = "{\"id\":\"9947\",\"name\":\"relation\",\"status\":2,\"type\":3,\"isSystem\": \
false,\"globallyUniqueId\":\"hD260BE2A30F9/9947\"}";
let result = serde_json::from_str::<Response<CollectionResponse>>(text);
assert_eq!(result.is_ok(), true, "failed: {:?}", result);
let text = "{\"error\":false,\"code\":412,\"id\":\"9947\",\"name\":\"relation\",\"status\"\
:2,\"type\":3,\"isSystem\": false,\"globallyUniqueId\":\"hD260BE2A30F9/9947\"}";
let result = serde_json::from_str::<Response<CollectionResponse>>(text);
assert_eq!(result.is_ok(), true, "failed: {:?}", result);
let text = "{\"error\":true,\"code\":412,\"errorMessage\":\"error\",\"errorNum\":1200}";
let result = serde_json::from_str::<Response<CollectionResponse>>(text);
assert_eq!(result.is_ok(), true, "failed: {:?}", result);
let response = Into::<Result<_, _>>::into(result.unwrap());
assert_eq!(
response.is_err(),
true,
"response should be error: {:?}",
response
);
}
}