1use crate::rpc::{typed_data::Data, TypedData};
2use chrono::{DateTime, FixedOffset, Utc};
3use serde::{de::Error, de::IntoDeserializer, Deserialize, Deserializer};
4use serde_json::from_str;
5use std::str::{from_utf8, FromStr};
6
7pub fn convert_from<'a, T>(data: &'a TypedData) -> Option<T>
8where
9 T: FromStr + Deserialize<'a>,
10{
11 match &data.data {
12 Some(Data::String(s)) => s.parse::<T>().ok(),
13 Some(Data::Json(s)) => from_str(s).ok(),
14 Some(Data::Bytes(b)) => {
15 if let Ok(s) = from_utf8(b) {
16 return s.parse::<T>().ok();
17 }
18 None
19 }
20 Some(Data::Stream(s)) => {
21 if let Ok(s) = from_utf8(s) {
22 return s.parse::<T>().ok();
23 }
24 None
25 }
26 Some(Data::Int(i)) => {
27 let deserializer: ::serde::de::value::I64Deserializer<::serde_json::error::Error> =
28 i.into_deserializer();
29 T::deserialize(deserializer).ok()
30 }
31 Some(Data::Double(d)) => {
32 let deserializer: ::serde::de::value::F64Deserializer<::serde_json::error::Error> =
33 d.into_deserializer();
34 T::deserialize(deserializer).ok()
35 }
36 _ => None,
37 }
38}
39
40pub fn deserialize_datetime<'a, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
41where
42 D: Deserializer<'a>,
43{
44 let mut s = String::deserialize(deserializer)?;
45
46 if s == "0001-01-01T00:00:00" {
49 s += "Z";
50 }
51
52 s.parse::<DateTime<FixedOffset>>()
53 .map_err(|e| Error::custom(format!("{}", e)))
54 .map(|dt| dt.with_timezone(&Utc))
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn it_converts_from_string_data() {
63 const DATA: &'static str = "test";
64
65 let data = TypedData {
66 data: Some(Data::String(DATA.to_string())),
67 };
68
69 let s: String = convert_from(&data).unwrap();
70 assert_eq!(s, DATA);
71 }
72
73 #[test]
74 fn it_converts_from_json_data() {
75 let data = TypedData {
76 data: Some(Data::Json(r#""hello world""#.to_string())),
77 };
78
79 let s: String = convert_from(&data).unwrap();
80 assert_eq!(s, "hello world");
81 }
82
83 #[test]
84 fn it_converts_from_bytes_data() {
85 let data = TypedData {
86 data: Some(Data::Bytes(vec![
87 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64,
88 ])),
89 };
90
91 let s: String = convert_from(&data).unwrap();
92 assert_eq!(s, "hello world");
93 }
94
95 #[test]
96 fn it_converts_from_stream_data() {
97 let data = TypedData {
98 data: Some(Data::Stream(vec![
99 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64,
100 ])),
101 };
102
103 let s: String = convert_from(&data).unwrap();
104 assert_eq!(s, "hello world");
105 }
106
107 #[test]
108 fn it_converts_from_int_data() {
109 const DATA: i64 = 42;
110
111 let data = TypedData {
112 data: Some(Data::Int(DATA)),
113 };
114
115 let d: i64 = convert_from(&data).unwrap();
116 assert_eq!(d, DATA);
117 }
118
119 #[test]
120 fn it_converts_from_double_data() {
121 const DATA: f64 = 42.24;
122
123 let data = TypedData {
124 data: Some(Data::Double(DATA)),
125 };
126
127 let d: f64 = convert_from(&data).unwrap();
128 assert_eq!(d, DATA);
129 }
130}