time_macros/
serde_format_description.rs
1use proc_macro::{Ident, TokenStream, TokenTree};
2
3pub(crate) fn build(
4 mod_name: Ident,
5 ty: TokenTree,
6 format: TokenStream,
7 format_description_display: String,
8) -> TokenStream {
9 let ty_s = &*ty.to_string();
10
11 let visitor = if cfg!(feature = "parsing") {
12 quote! {
13 struct Visitor;
14 struct OptionVisitor;
15
16 impl<'a> ::serde::de::Visitor<'a> for Visitor {
17 type Value = __TimeSerdeType;
18
19 fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
20 write!(
21 f,
22 concat!(
23 "a(n) `",
24 #(ty_s),
25 "` in the format \"{}\"",
26 ),
27 #(format_description_display.as_str())
28 )
29 }
30
31 fn visit_str<E: ::serde::de::Error>(
32 self,
33 value: &str
34 ) -> Result<__TimeSerdeType, E> {
35 __TimeSerdeType::parse(value, &description()).map_err(E::custom)
36 }
37 }
38
39 impl<'a> ::serde::de::Visitor<'a> for OptionVisitor {
40 type Value = Option<__TimeSerdeType>;
41
42 fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
43 write!(
44 f,
45 concat!(
46 "an `Option<",
47 #(ty_s),
48 ">` in the format \"{}\"",
49 ),
50 #(format_description_display.as_str())
51 )
52 }
53
54 fn visit_some<D: ::serde::de::Deserializer<'a>>(
55 self,
56 deserializer: D
57 ) -> Result<Option<__TimeSerdeType>, D::Error> {
58 deserializer
59 .deserialize_str(Visitor)
60 .map(Some)
61 }
62
63 fn visit_none<E: ::serde::de::Error>(
64 self
65 ) -> Result<Option<__TimeSerdeType>, E> {
66 Ok(None)
67 }
68 }
69 }
70 } else {
71 quote!()
72 };
73
74 let serialize_primary = if cfg!(feature = "formatting") {
75 quote! {
76 pub fn serialize<S: ::serde::Serializer>(
77 datetime: &__TimeSerdeType,
78 serializer: S,
79 ) -> Result<S::Ok, S::Error> {
80 use ::serde::Serialize;
81 datetime
82 .format(&description())
83 .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
84 .serialize(serializer)
85 }
86 }
87 } else {
88 quote!()
89 };
90
91 let deserialize_primary = if cfg!(feature = "parsing") {
92 quote! {
93 pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
94 deserializer: D
95 ) -> Result<__TimeSerdeType, D::Error> {
96 use ::serde::Deserialize;
97 deserializer.deserialize_str(Visitor)
98 }
99 }
100 } else {
101 quote!()
102 };
103
104 let serialize_option = if cfg!(feature = "formatting") {
105 quote! {
106 pub fn serialize<S: ::serde::Serializer>(
107 option: &Option<__TimeSerdeType>,
108 serializer: S,
109 ) -> Result<S::Ok, S::Error> {
110 use ::serde::Serialize;
111 option.map(|datetime| datetime.format(&description()))
112 .transpose()
113 .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
114 .serialize(serializer)
115 }
116 }
117 } else {
118 quote!()
119 };
120
121 let deserialize_option = if cfg!(feature = "parsing") {
122 quote! {
123 pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
124 deserializer: D
125 ) -> Result<Option<__TimeSerdeType>, D::Error> {
126 use ::serde::Deserialize;
127 deserializer.deserialize_option(OptionVisitor)
128 }
129 }
130 } else {
131 quote!()
132 };
133
134 let deserialize_option_imports = if cfg!(feature = "parsing") {
135 quote! {
136 use super::{OptionVisitor, Visitor};
137 }
138 } else {
139 quote!()
140 };
141
142 let fd_traits = match (cfg!(feature = "formatting"), cfg!(feature = "parsing")) {
143 (false, false) => {
144 bug!("serde_format_description::build called without formatting or parsing enabled")
145 }
146 (false, true) => quote! { ::time::parsing::Parsable },
147 (true, false) => quote! { ::time::formatting::Formattable },
148 (true, true) => quote! { ::time::formatting::Formattable + ::time::parsing::Parsable },
149 };
150
151 quote! {
152 mod #(mod_name) {
153 use super::*;
154 use ::time::#(ty) as __TimeSerdeType;
156
157 const fn description() -> impl #S(fd_traits) {
158 #S(format)
159 }
160
161 #S(visitor)
162 #S(serialize_primary)
163 #S(deserialize_primary)
164
165 pub(super) mod option {
166 use super::{description, __TimeSerdeType};
167 #S(deserialize_option_imports)
168
169 #S(serialize_option)
170 #S(deserialize_option)
171 }
172 }
173 }
174}