greg/real/
serde.rs

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
60/*
61 *	POINT
62 */
63
64serialize_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
75/*
76 *	SPAN
77 */
78
79serialize_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	/// [`fmt::Formatter`] is the only [`Serializer`] without extra deps
102	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}