1use std::fmt;
2
3use serde::{
4 Serialize,
5 Serializer,
6 Deserialize,
7 Deserializer
8};
9use serde::de::{
10 Error,
11 Visitor,
12};
13
14use super::{
15 Point,
16 Span,
17};
18
19macro_rules! serialize_field {
20 ($Type:ty, $field:ident) => {
21 impl Serialize for $Type {
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where S: Serializer
24 {
25 self.$field.serialize(serializer)
26 }
27 }
28 }
29}
30
31macro_rules! deserialize {
32 (
33 $Type:ty,
34 $Visitor:ident,
35 $expect:literal,
36 $f:ident,
37 $( $methods:item )+ ) =>
38 {
39 struct $Visitor;
40
41 impl<'de,> Visitor<'de> for $Visitor {
42 type Value = $Type;
43
44 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
45 formatter.write_str($expect)
46 }
47 $( $methods )+
48 }
49
50 impl<'de> Deserialize<'de> for $Type {
51 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
52 where D: Deserializer<'de>
53 {
54 deserializer.$f($Visitor)
55 }
56 }
57 }
58}
59
60serialize_field!(Point, timestamp);
65deserialize!(
66 Point,
67 PointVisitor,
68 "a 64-bit timestamp",
69 deserialize_i64,
70 fn visit_i64<E: Error>(self, value: i64) -> Result<Self::Value, E> {
71 Ok(Point::from_epoch(value))
72 }
73);
74
75serialize_field!(Span, seconds);
80deserialize!(
81 Span,
82 SpanVisitor,
83 "a 64-bit duration in seconds",
84 deserialize_u64,
85 fn visit_u64<E: Error>(self, value: u64) -> Result<Self::Value, E> {
86 Ok(Span::from_seconds(value))
87 }
88 fn visit_i64<E: Error>(self, value: i64) -> Result<Self::Value, E> {
89 value.try_into()
90 .map(Span::from_seconds)
91 .map_err(E::custom)
92 }
93);
94
95#[cfg(test)]
96mod tests {
97 use std::fmt;
98 use serde::de::value;
99 use super::*;
100
101 struct FmtAbuser<T>(T);
103 impl<T: Serialize> fmt::Display for FmtAbuser<T> {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 self.0.serialize(f)
106 }
107 }
108 macro_rules! assert_serialize_eq {
109 ($a:expr, $b:expr) => {
110 assert_eq!(
111 FmtAbuser($a).to_string(),
112 FmtAbuser($b).to_string()
113 );
114 };
115 }
116
117 #[test]
118 fn point() {
119 type Ser = value::I64Deserializer<value::Error>;
120
121 let cases = [
122 i64::MIN,
123 i32::MIN.into(),
124 0,
125 Point::now().timestamp,
126 i32::MAX.into(),
127 u32::MAX.into(),
128 i64::MAX
129 ];
130 for case in cases {
131 let before = Point::from_epoch(case);
132 let after = Point::deserialize(Ser::new(case)).unwrap();
133 assert_eq!(before, after);
134
135 assert_serialize_eq!(before, case);
136 }
137 }
138
139 #[test]
140 fn span() {
141 type Ser = value::U64Deserializer<value::Error>;
142
143 let cases = [
144 Span::ZERO,
145 Span::SECOND,
146 Span::MINUTE,
147 Span::HOUR,
148 Span::DAY,
149 Span::WEEK,
150 Span::from_seconds(u32::MAX.into()),
151 Span::from_seconds(u64::MAX),
152 ];
153 for case in cases {
154 let after = Span::deserialize(Ser::new(case.seconds)).unwrap();
155 assert_eq!(case, after);
156
157 assert_serialize_eq!(case, case.seconds);
158 }
159 }
160}