#![allow(unused)] use std::collections::{BTreeMap, HashMap}; use chrono::{serde::ts_nanoseconds::deserialize, DateTime, NaiveDateTime, Utc}; use serde::de::{Deserialize, Deserializer, Error, Unexpected, Visitor}; pub(crate) fn empty_string_is_none<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let s: &str = Deserialize::deserialize(deserializer)?; if s.is_empty() { Ok(None) } else { Ok(Some(s)) } } pub(crate) fn string_is_long<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; if s.is_empty() { Ok(None) } else { s.parse() .map(Some) .map_err(|_e| Error::invalid_type(Unexpected::Str(&s), &"i64")) } } pub(crate) fn zero_date_is_none<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { let i = i64::deserialize(deserializer)?; if i == 0 { Ok(None) } else { let naive = NaiveDateTime::from_timestamp_opt(i, 0) .ok_or_else(|| D::Error::invalid_value(Unexpected::Signed(i), &"Epoch timestamp"))?; Ok(Some(DateTime::from_utc(naive, Utc))) } } pub(crate) fn int_is_bool<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let i = i64::deserialize(deserializer)?; match i { 0 => Ok(false), 1 => Ok(true), x => Err(Error::invalid_value(Unexpected::Signed(x), &"0 or 1")), } } pub(crate) fn empty_string_int_option<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { struct DumbVisitor; impl<'de> Visitor<'de> for DumbVisitor { type Value = Option; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "Empty string or integer") } // serde_json will treat all unsigned integers as u64 fn visit_u64(self, v: u64) -> Result where E: Error, { Ok(Some(v as i32)) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: Error, { if v.is_empty() { Ok(None) } else { Err(E::invalid_value(Unexpected::Str(v), &self)) } } } deserializer.deserialize_any(DumbVisitor) } pub(crate) fn datetime_map<'de, D>( deserializer: D, ) -> Result>, D::Error> where D: Deserializer<'de>, { #[derive(serde::Deserialize)] struct UnixTimestamp( #[serde(with = "chrono::serde::ts_seconds")] chrono::DateTime, ); struct MapVisitor; impl<'de> Visitor<'de> for MapVisitor { type Value = BTreeMap>; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "map of unix timestamps") } fn visit_map(self, mut map: A) -> Result where A: serde::de::MapAccess<'de>, { let mut result = BTreeMap::new(); while let Some(key) = map.next_key::<&'de str>()? { let id = key .parse() .map_err(|_e| A::Error::invalid_value(Unexpected::Str(key), &"integer"))?; let ts: UnixTimestamp = map.next_value()?; result.insert(id, ts.0); } Ok(result) } } deserializer.deserialize_map(MapVisitor) } pub(crate) fn empty_dict_is_empty_array<'de, D, T>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, T: Deserialize<'de>, { struct ArrayVisitor(std::marker::PhantomData); impl<'de, T> Visitor<'de> for ArrayVisitor where T: Deserialize<'de>, { type Value = Vec; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "vec or empty object") } fn visit_map(self, map: A) -> Result where A: serde::de::MapAccess<'de>, { match map.size_hint() { Some(0) | None => Ok(Vec::default()), Some(len) => Err(A::Error::invalid_length(len, &"empty dict")), } } fn visit_seq(self, mut seq: A) -> Result where A: serde::de::SeqAccess<'de>, { let mut result = match seq.size_hint() { Some(len) => Vec::with_capacity(len), None => Vec::default(), }; while let Some(element) = seq.next_element()? { result.push(element); } Ok(result) } } deserializer.deserialize_any(ArrayVisitor(std::marker::PhantomData)) } pub(crate) fn null_is_empty_dict<'de, D, K, V>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, K: std::hash::Hash + std::cmp::Eq + Deserialize<'de>, V: Deserialize<'de>, { Ok(Option::deserialize(deserializer)?.unwrap_or_default()) } #[cfg(feature = "decimal")] pub(crate) fn string_or_decimal<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { struct DumbVisitor; impl<'de> Visitor<'de> for DumbVisitor { type Value = rust_decimal::Decimal; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "integer or float as string") } fn visit_u64(self, v: u64) -> Result where E: Error, { Ok(v.into()) } fn visit_i64(self, v: i64) -> Result where E: Error, { Ok(v.into()) } fn visit_str(self, v: &str) -> Result where E: Error, { rust_decimal::Decimal::from_str_exact(v).map_err(E::custom) } } deserializer.deserialize_any(DumbVisitor) }