1pub mod min_api;
2pub mod data_api;
3
4
5use serde::{Deserialize, Deserializer};
6
7
8#[derive(Debug, PartialEq)]
9pub enum StringOrInt {
11 String(String),
12 Int64(i64),
13 UInt64(u64),
14}
15
16impl<'de> Deserialize<'de> for StringOrInt {
17 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
18 struct Visitor;
19
20 impl<'de> serde::de::Visitor<'de> for Visitor {
21 type Value = StringOrInt;
22
23 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24 write!(f, "a String, i64 or u64")
25 }
26
27 fn visit_string<E: serde::de::Error>(self, s: String) -> Result<Self::Value, E> {
28 Ok(StringOrInt::String(s))
29 }
30
31 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
32 Ok(StringOrInt::Int64(v))
33 }
34
35 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
36 Ok(StringOrInt::UInt64(v))
37 }
38 }
39
40 deserializer.deserialize_any(Visitor)
41 }
42}
43
44
45#[derive(Deserialize, Debug)]
49pub struct CCCallsMade {
50 pub second: i32,
51 pub minute: i32,
52 pub hour: i32,
53 pub day: i32,
54 pub month: i32,
55 pub total_calls: i32,
56}
57
58#[derive(Deserialize, Debug)]
59pub struct CCMaxCalls {
60 pub second: i32,
61 pub minute: i32,
62 pub hour: i32,
63 pub day: i32,
64 pub month: i32,
65}
66
67#[derive(Deserialize, Debug)]
68pub struct CCRateLimit {
69 pub calls_made: Option<CCCallsMade>,
70 pub max_calls: Option<CCMaxCalls>,
71}
72
73#[derive(Deserialize, Debug)]
74pub struct CCMinWrapper<T> {
75 #[serde(rename = "Aggregated")]
76 pub aggregated: Option<bool>,
77 #[serde(rename = "TimeFrom")]
78 pub time_from: Option<i64>,
79 #[serde(rename = "TimeTo")]
80 pub time_to: Option<i64>,
81 #[serde(rename = "Data")]
82 pub data: Option<T>,
83}
84
85#[derive(Deserialize, Debug)]
86pub struct CCMinResponse<T> {
87 #[serde(rename = "Response")]
88 pub response: String,
89 #[serde(rename = "Message")]
90 pub message: String,
91 #[serde(rename = "HasWarning")]
92 pub has_warning: bool,
93 #[serde(rename = "Type")]
94 pub type_: i32,
95 #[serde(rename = "Data")]
96 pub data: Option<T>,
97 #[serde(rename = "RateLimit")]
98 pub rate_limit: Option<CCRateLimit>,
99}
100
101
102#[derive(Deserialize, Debug)]
106pub struct CCErrorOtherInfo {
107 pub param: Option<String>,
109 pub values: Option<Vec<StringOrInt>>,
111 pub instrument_status: Option<String>,
114 pub first: Option<i64>,
116 pub last: Option<i64>,
118 pub first_bucket: Option<i64>,
120}
121
122#[derive(Deserialize, Debug)]
123pub struct CCError {
126 #[serde(rename = "type")]
127 pub type_: i32,
129 pub message: String,
131 pub other_info: Option<CCErrorOtherInfo>,
132}
133
134#[derive(Deserialize, Debug)]
135pub struct CCDataResponse<T> {
136 #[serde(rename = "Data")]
137 pub data: Option<T>,
138 #[serde(rename = "Err")]
139 pub error: Option<CCError>,
143}
144
145
146#[cfg(test)]
147mod tests {
148
149 #[test]
150 fn unit_test_nullable_field() -> () {
151 use serde_json;
152 use crate::schemas;
153 let d: String = String::from("{\"Data\":{}, \"Err\":{\"type\": 23, \"message\": \"hello\", \"other_info\":null}}");
154 let response: schemas::CCDataResponse<String> = serde_json::from_str(&d.to_string().replace("{}", "null")).unwrap();
155 assert_eq!(response.data, None);
156 }
157}