summaryrefslogtreecommitdiffstats
path: root/vendor/time-macros/src/serde_format_description.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/time-macros/src/serde_format_description.rs')
-rw-r--r--vendor/time-macros/src/serde_format_description.rs163
1 files changed, 163 insertions, 0 deletions
diff --git a/vendor/time-macros/src/serde_format_description.rs b/vendor/time-macros/src/serde_format_description.rs
new file mode 100644
index 000000000..c09a4e9e2
--- /dev/null
+++ b/vendor/time-macros/src/serde_format_description.rs
@@ -0,0 +1,163 @@
+use proc_macro::{Ident, TokenStream, TokenTree};
+
+pub(crate) fn build(
+ mod_name: Ident,
+ ty: TokenTree,
+ format: TokenStream,
+ raw_format_string: Option<String>,
+) -> TokenStream {
+ let ty_s = &*ty.to_string();
+
+ let format_description_display = raw_format_string.unwrap_or_else(|| format.to_string());
+
+ let visitor = if cfg!(feature = "parsing") {
+ quote! {
+ struct Visitor;
+ struct OptionVisitor;
+
+ impl<'a> ::serde::de::Visitor<'a> for Visitor {
+ type Value = __TimeSerdeType;
+
+ fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ write!(
+ f,
+ concat!(
+ "a(n) `",
+ #(ty_s),
+ "` in the format \"{}\"",
+ ),
+ #(format_description_display.as_str())
+ )
+ }
+
+ fn visit_str<E: ::serde::de::Error>(
+ self,
+ value: &str
+ ) -> Result<__TimeSerdeType, E> {
+ __TimeSerdeType::parse(value, &DESCRIPTION).map_err(E::custom)
+ }
+ }
+
+ impl<'a> ::serde::de::Visitor<'a> for OptionVisitor {
+ type Value = Option<__TimeSerdeType>;
+
+ fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ write!(
+ f,
+ concat!(
+ "an `Option<",
+ #(ty_s),
+ ">` in the format \"{}\"",
+ ),
+ #(format_description_display.as_str())
+ )
+ }
+
+ fn visit_some<D: ::serde::de::Deserializer<'a>>(
+ self,
+ deserializer: D
+ ) -> Result<Option<__TimeSerdeType>, D::Error> {
+ deserializer
+ .deserialize_any(Visitor)
+ .map(Some)
+ }
+
+ fn visit_none<E: ::serde::de::Error>(
+ self
+ ) -> Result<Option<__TimeSerdeType>, E> {
+ Ok(None)
+ }
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let serialize_primary = if cfg!(feature = "formatting") {
+ quote! {
+ pub fn serialize<S: ::serde::Serializer>(
+ datetime: &__TimeSerdeType,
+ serializer: S,
+ ) -> Result<S::Ok, S::Error> {
+ use ::serde::Serialize;
+ datetime
+ .format(&DESCRIPTION)
+ .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
+ .serialize(serializer)
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let deserialize_primary = if cfg!(feature = "parsing") {
+ quote! {
+ pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
+ deserializer: D
+ ) -> Result<__TimeSerdeType, D::Error> {
+ use ::serde::Deserialize;
+ deserializer.deserialize_any(Visitor)
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let serialize_option = if cfg!(feature = "formatting") {
+ quote! {
+ pub fn serialize<S: ::serde::Serializer>(
+ option: &Option<__TimeSerdeType>,
+ serializer: S,
+ ) -> Result<S::Ok, S::Error> {
+ use ::serde::Serialize;
+ option.map(|datetime| datetime.format(&DESCRIPTION))
+ .transpose()
+ .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
+ .serialize(serializer)
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let deserialize_option = if cfg!(feature = "parsing") {
+ quote! {
+ pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
+ deserializer: D
+ ) -> Result<Option<__TimeSerdeType>, D::Error> {
+ use ::serde::Deserialize;
+ deserializer.deserialize_option(OptionVisitor)
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let deserialize_option_imports = if cfg!(feature = "parsing") {
+ quote! {
+ use super::{OptionVisitor, Visitor};
+ }
+ } else {
+ quote!()
+ };
+
+ quote! {
+ mod #(mod_name) {
+ use ::time::#(ty) as __TimeSerdeType;
+
+ const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = #S(format);
+
+ #S(visitor)
+ #S(serialize_primary)
+ #S(deserialize_primary)
+
+ pub(super) mod option {
+ use super::{DESCRIPTION, __TimeSerdeType};
+ #S(deserialize_option_imports)
+
+ #S(serialize_option)
+ #S(deserialize_option)
+ }
+ }
+ }
+}