pub mod min_api;
pub mod data_api;
use std::io::Error;
use serde::Deserialize;
use crate::utils::some_or_error;
#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
pub enum EmptyObject<T> {
Some(T),
None {},
}
impl<T> From<EmptyObject<T>> for Option<T> {
fn from(empty_object: EmptyObject<T>) -> Option<T> {
match empty_object {
EmptyObject::Some(v) => Some(v),
EmptyObject::None { } => None,
}
}
}
impl<T> From<Option<T>> for EmptyObject<T> {
fn from(option: Option<T>) -> EmptyObject <T> {
match option {
Some(v) => EmptyObject::Some(v),
None => EmptyObject::None { },
}
}
}
impl<T> EmptyObject<T> {
pub fn into_option(self) -> Option<T> {
self.into()
}
pub fn as_option(&self) -> Option<&T> {
match self {
EmptyObject::Some(v) => Some(v),
EmptyObject::None {} => None,
}
}
}
pub trait DataUnwrap<T> {
fn data_unwrap(self) -> Result<T, Error>;
}
#[derive(Deserialize, Debug)]
pub struct CCCallsMade {
pub second: i32,
pub minute: i32,
pub hour: i32,
pub day: i32,
pub month: i32,
pub total_calls: i32,
}
#[derive(Deserialize, Debug)]
pub struct CCMaxCalls {
pub second: i32,
pub minute: i32,
pub hour: i32,
pub day: i32,
pub month: i32,
}
#[derive(Deserialize, Debug)]
pub struct CCRateLimit {
pub calls_made: Option<CCCallsMade>,
pub max_calls: Option<CCMaxCalls>,
}
#[derive(Deserialize, Debug)]
pub struct CCMinWrapper<T> {
#[serde(rename = "Aggregated")]
pub aggregated: Option<bool>,
#[serde(rename = "TimeFrom")]
pub time_from: Option<i64>,
#[serde(rename = "TimeTo")]
pub time_to: Option<i64>,
#[serde(rename = "Data")]
pub data: Option<T>,
}
impl<T> DataUnwrap<T> for CCMinWrapper<T> {
fn data_unwrap(self) -> Result<T, Error> {
some_or_error(self.data, "No data inside the CCMinWrapper.")
}
}
#[derive(Deserialize, Debug)]
pub struct CCMinResponse<T> {
#[serde(rename = "Response")]
pub response: String,
#[serde(rename = "Message")]
pub message: String,
#[serde(rename = "HasWarning")]
pub has_warning: bool,
#[serde(rename = "Type")]
pub type_: i32,
#[serde(rename = "Data")]
pub data: EmptyObject<T>,
#[serde(rename = "RateLimit")]
pub rate_limit: Option<CCRateLimit>,
}
impl<T> DataUnwrap<T> for CCMinResponse<T> {
fn data_unwrap(self) -> Result<T, Error> {
some_or_error(self.data.into_option(), "No data inside the CCMinResponse.")
}
}
#[derive(Deserialize, Debug)]
pub struct CCErrorOtherInfo {
pub param: Option<String>,
pub values: Option<Vec<String>>,
}
#[derive(Deserialize, Debug)]
pub struct CCError {
#[serde(rename = "type")]
pub type_: i32,
pub message: String,
pub other_info: Option<CCErrorOtherInfo>,
}
#[derive(Deserialize, Debug)]
pub struct CCDataResponse<T> {
#[serde(rename = "Data")]
pub data: EmptyObject<T>,
#[serde(rename = "Err")]
pub error: EmptyObject<CCError>,
}
impl<T> DataUnwrap<T> for CCDataResponse<T> {
fn data_unwrap(self) -> Result<T, Error> {
some_or_error(self.data.into_option(), "No data inside the CCDataResponse.")
}
}
#[cfg(test)]
mod tests {
#[test]
fn unit_test_nullable_field() -> () {
use serde_json;
use crate::schemas;
let d: String = String::from("{\"Data\":{}, \"Err\":{\"type\": 23, \"message\": \"hello\", \"other_info\":null}}");
let response: schemas::CCDataResponse<String> = serde_json::from_str(&d.to_string()).unwrap();
assert_eq!(response.data.into_option(), None);
}
}