time_macros/
serde_format_description.rs1use 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 #[allow(clippy::ref_option)]
107 pub fn serialize<S: ::serde::Serializer>(
108 option: &Option<__TimeSerdeType>,
109 serializer: S,
110 ) -> Result<S::Ok, S::Error> {
111 use ::serde::Serialize;
112 option.map(|datetime| datetime.format(&description()))
113 .transpose()
114 .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
115 .serialize(serializer)
116 }
117 }
118 } else {
119 quote!()
120 };
121
122 let deserialize_option = if cfg!(feature = "parsing") {
123 quote! {
124 pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
125 deserializer: D
126 ) -> Result<Option<__TimeSerdeType>, D::Error> {
127 use ::serde::Deserialize;
128 deserializer.deserialize_option(OptionVisitor)
129 }
130 }
131 } else {
132 quote!()
133 };
134
135 let deserialize_option_imports = if cfg!(feature = "parsing") {
136 quote! {
137 use super::{OptionVisitor, Visitor};
138 }
139 } else {
140 quote!()
141 };
142
143 let fd_traits = match (cfg!(feature = "formatting"), cfg!(feature = "parsing")) {
144 (false, false) => {
145 bug!("serde_format_description::build called without formatting or parsing enabled")
146 }
147 (false, true) => quote! { ::time::parsing::Parsable },
148 (true, false) => quote! { ::time::formatting::Formattable },
149 (true, true) => quote! { ::time::formatting::Formattable + ::time::parsing::Parsable },
150 };
151
152 quote! {
153 mod #(mod_name) {
154 use super::*;
155 use ::time::#(ty) as __TimeSerdeType;
157
158 const fn description() -> impl #S(fd_traits) {
159 #S(format)
160 }
161
162 #S(visitor)
163 #S(serialize_primary)
164 #S(deserialize_primary)
165
166 pub(super) mod option {
167 use super::{description, __TimeSerdeType};
168 #S(deserialize_option_imports)
169
170 #S(serialize_option)
171 #S(deserialize_option)
172 }
173 }
174 }
175}