nym_api_requests/models/
schema_helpers.rs1use crate::helpers::unix_epoch;
5use cosmwasm_std::Uint128;
6use schemars::schema::{InstanceType, Schema, SchemaObject};
7use schemars::{JsonSchema, SchemaGenerator};
8use serde::{Deserialize, Deserializer, Serialize};
9use std::fmt;
10use std::fmt::{Display, Formatter};
11use std::ops::{Deref, DerefMut};
12use time::OffsetDateTime;
13use utoipa::ToSchema;
14
15#[derive(ToSchema)]
16#[schema(title = "Coin")]
17pub struct CoinSchema {
18 pub denom: String,
19 #[schema(value_type = String)]
20 pub amount: Uint128,
21}
22
23pub fn de_rfc3339_or_default<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
24where
25 D: Deserializer<'de>,
26{
27 Ok(time::serde::rfc3339::deserialize(deserializer).unwrap_or_else(|_| unix_epoch()))
28}
29
30#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, ToSchema)]
32pub struct OffsetDateTimeJsonSchemaWrapper(
33 #[serde(
34 default = "unix_epoch",
35 with = "crate::helpers::overengineered_offset_date_time_serde"
36 )]
37 #[schema(inline)]
38 pub OffsetDateTime,
39);
40
41impl Default for OffsetDateTimeJsonSchemaWrapper {
42 fn default() -> Self {
43 OffsetDateTimeJsonSchemaWrapper(unix_epoch())
44 }
45}
46
47impl Display for OffsetDateTimeJsonSchemaWrapper {
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 Display::fmt(&self.0, f)
50 }
51}
52
53impl From<OffsetDateTimeJsonSchemaWrapper> for OffsetDateTime {
54 fn from(value: OffsetDateTimeJsonSchemaWrapper) -> Self {
55 value.0
56 }
57}
58
59impl From<OffsetDateTime> for OffsetDateTimeJsonSchemaWrapper {
60 fn from(value: OffsetDateTime) -> Self {
61 OffsetDateTimeJsonSchemaWrapper(value)
62 }
63}
64
65impl Deref for OffsetDateTimeJsonSchemaWrapper {
66 type Target = OffsetDateTime;
67
68 fn deref(&self) -> &Self::Target {
69 &self.0
70 }
71}
72
73impl DerefMut for OffsetDateTimeJsonSchemaWrapper {
74 fn deref_mut(&mut self) -> &mut Self::Target {
75 &mut self.0
76 }
77}
78
79impl JsonSchema for OffsetDateTimeJsonSchemaWrapper {
81 fn is_referenceable() -> bool {
82 false
83 }
84
85 fn schema_name() -> String {
86 "DateTime".into()
87 }
88
89 fn json_schema(_: &mut SchemaGenerator) -> Schema {
90 SchemaObject {
91 instance_type: Some(InstanceType::String.into()),
92 format: Some("date-time".into()),
93 ..Default::default()
94 }
95 .into()
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use std::time::Duration;
103
104 #[test]
105 fn offset_date_time_json_schema_wrapper_serde_backwards_compat() {
106 let mut dummy = OffsetDateTimeJsonSchemaWrapper::default();
107 dummy.0 += Duration::from_millis(1);
108 let ser = serde_json::to_string(&dummy).unwrap();
109
110 assert_eq!("\"1970-01-01 00:00:00.001 +00:00:00\"", ser);
111
112 let human_readable = "\"2024-05-23 07:41:02.756283766 +00:00:00\"";
113 let rfc3339 = "\"2002-10-02T15:00:00Z\"";
114 let rfc3339_offset = "\"2002-10-02T10:00:00-05:00\"";
115
116 let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(human_readable).unwrap();
117 assert_eq!(de.0.unix_timestamp(), 1716450062);
118
119 let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(rfc3339).unwrap();
120 assert_eq!(de.0.unix_timestamp(), 1033570800);
121
122 let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(rfc3339_offset).unwrap();
123 assert_eq!(de.0.unix_timestamp(), 1033570800);
124
125 let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>("\"nonsense\"").unwrap();
126 assert_eq!(de.0.unix_timestamp(), 0);
127 }
128}