#[cfg(any(feature = "chrono", feature = "url"))]
use serde::Deserialize;
#[cfg(any(feature = "chrono", feature = "url"))]
use serde::Deserializer;
#[cfg(any(feature = "chrono", feature = "url"))]
use serde::Serializer;
pub(crate) use crate::finite_float::float32;
pub(crate) use crate::finite_float::float32_vec;
pub(crate) use crate::finite_float::float64;
pub(crate) use crate::finite_float::float64_vec;
pub(crate) use crate::wide_integer::int128;
pub(crate) use crate::wide_integer::int128_vec;
pub(crate) use crate::wide_integer::uint128;
pub(crate) use crate::wide_integer::uint128_vec;
pub(crate) mod string_map;
pub(crate) mod string_map_vec;
#[cfg(feature = "json")]
pub(crate) mod json;
#[cfg(feature = "json")]
pub(crate) mod json_vec;
#[cfg(feature = "big-integer")]
mod decimal;
mod internal;
#[cfg(feature = "big-decimal")]
use self::internal::BigDecimalPayload;
use self::internal::DurationPayload;
#[cfg(feature = "big-decimal")]
pub(crate) const MAX_BIG_DECIMAL_ABSOLUTE_SCALE: i64 = 150_000;
#[must_use]
#[cfg(feature = "big-decimal")]
#[inline(always)]
pub(crate) const fn is_valid_big_decimal_scale(scale: i64) -> bool {
scale.unsigned_abs() <= MAX_BIG_DECIMAL_ABSOLUTE_SCALE as u64
}
#[cfg(any(feature = "chrono", feature = "url"))]
fn serialize_canonical<S, T, F>(value: &T, serializer: S, format: F) -> Result<S::Ok, S::Error>
where
S: Serializer,
F: FnOnce(&T) -> String,
{
serializer.serialize_str(&format(value))
}
#[cfg(any(feature = "chrono", feature = "url"))]
fn deserialize_canonical<'de, D, T, P, F>(deserializer: D, parse: P, format: F) -> Result<T, D::Error>
where
D: Deserializer<'de>,
P: FnOnce(&str) -> Result<T, String>,
F: FnOnce(&T) -> String,
{
use serde::de::Error as _;
let input = String::deserialize(deserializer)?;
let value = parse(&input).map_err(D::Error::custom)?;
if format(&value) != input {
return Err(D::Error::custom("non-canonical V1 string payload"));
}
Ok(value)
}
#[cfg(any(feature = "chrono", feature = "url"))]
fn serialize_canonical_vec<S, T, F>(values: &[T], serializer: S, format: F) -> Result<S::Ok, S::Error>
where
S: Serializer,
F: Fn(&T) -> String,
{
serializer.collect_seq(values.iter().map(format))
}
#[cfg(any(feature = "chrono", feature = "url"))]
fn deserialize_canonical_vec<'de, D, T, P, F>(deserializer: D, parse: P, format: F) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
P: Fn(&str) -> Result<T, String>,
F: Fn(&T) -> String,
{
use serde::de::Error as _;
Vec::<String>::deserialize(deserializer)?
.into_iter()
.map(|input| {
let value = parse(&input).map_err(D::Error::custom)?;
if format(&value) != input {
return Err(D::Error::custom("non-canonical V1 string payload"));
}
Ok(value)
})
.collect()
}
#[cfg(feature = "chrono")]
macro_rules! define_chrono_wire {
($scalar:ident, $vector:ident, $type:ty, $parse:expr, $format:expr) => {
pub(crate) mod $scalar {
use serde::Deserializer;
use serde::Serializer;
pub(crate) fn serialize<S>(value: &$type, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
super::serialize_canonical(value, serializer, $format)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<$type, D::Error>
where
D: Deserializer<'de>,
{
super::deserialize_canonical(deserializer, $parse, $format)
}
}
pub(crate) mod $vector {
use serde::Deserializer;
use serde::Serializer;
pub(crate) fn serialize<S>(values: &[$type], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
super::serialize_canonical_vec(values, serializer, $format)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<$type>, D::Error>
where
D: Deserializer<'de>,
{
super::deserialize_canonical_vec(deserializer, $parse, $format)
}
}
};
}
#[cfg(feature = "chrono")]
define_chrono_wire!(
date,
date_vec,
chrono::NaiveDate,
|input| chrono::NaiveDate::parse_from_str(input, "%F").map_err(|error| error.to_string()),
|value: &chrono::NaiveDate| value.format("%F").to_string()
);
#[cfg(feature = "chrono")]
define_chrono_wire!(
time,
time_vec,
chrono::NaiveTime,
|input| chrono::NaiveTime::parse_from_str(input, "%H:%M:%S%.f").map_err(|error| error.to_string()),
|value: &chrono::NaiveTime| value.format("%H:%M:%S%.f").to_string()
);
#[cfg(feature = "chrono")]
define_chrono_wire!(
datetime,
datetime_vec,
chrono::NaiveDateTime,
|input| chrono::NaiveDateTime::parse_from_str(input, "%Y-%m-%dT%H:%M:%S%.f").map_err(|error| error.to_string()),
|value: &chrono::NaiveDateTime| value.format("%Y-%m-%dT%H:%M:%S%.f").to_string()
);
#[cfg(feature = "chrono")]
define_chrono_wire!(
instant,
instant_vec,
chrono::DateTime<chrono::Utc>,
|input| chrono::DateTime::parse_from_rfc3339(input)
.map(|value| value.with_timezone(&chrono::Utc))
.map_err(|error| error.to_string()),
|value: &chrono::DateTime<chrono::Utc>| value.to_rfc3339_opts(chrono::SecondsFormat::AutoSi, true)
);
#[cfg(feature = "url")]
macro_rules! define_url_wire {
() => {
pub(crate) mod url {
use serde::Deserializer;
use serde::Serializer;
pub(crate) fn serialize<S>(value: &::url::Url, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
super::serialize_canonical(value, serializer, |value: &::url::Url| value.as_str().to_owned())
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<::url::Url, D::Error>
where
D: Deserializer<'de>,
{
super::deserialize_canonical(
deserializer,
|input| ::url::Url::parse(input).map_err(|error| error.to_string()),
|value: &::url::Url| value.as_str().to_owned(),
)
}
}
pub(crate) mod url_vec {
use serde::Deserializer;
use serde::Serializer;
pub(crate) fn serialize<S>(values: &[::url::Url], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
super::serialize_canonical_vec(values, serializer, |value: &::url::Url| value.as_str().to_owned())
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<::url::Url>, D::Error>
where
D: Deserializer<'de>,
{
super::deserialize_canonical_vec(
deserializer,
|input| ::url::Url::parse(input).map_err(|error| error.to_string()),
|value: &::url::Url| value.as_str().to_owned(),
)
}
}
};
}
#[cfg(feature = "url")]
define_url_wire!();
#[cfg(feature = "big-integer")]
macro_rules! define_decimal_serde {
($scalar_module:ident, $vector_module:ident, $type:ty) => {
pub(crate) mod $scalar_module {
use serde::Deserializer;
use serde::Serializer;
use super::decimal;
pub(crate) fn serialize<S>(value: &$type, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
decimal::serialize(value, serializer)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<$type, D::Error>
where
D: Deserializer<'de>,
{
decimal::deserialize(deserializer)
}
}
pub(crate) mod $vector_module {
use serde::Deserializer;
use serde::Serializer;
use super::decimal;
pub(crate) fn serialize<S>(values: &[$type], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
decimal::serialize_vec(values, serializer)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<$type>, D::Error>
where
D: Deserializer<'de>,
{
decimal::deserialize_vec(deserializer)
}
}
};
}
#[cfg(feature = "big-integer")]
define_decimal_serde!(big_integer, big_integer_vec, num_bigint::BigInt);
#[cfg(feature = "big-decimal")]
pub(crate) mod big_decimal {
use bigdecimal::BigDecimal;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use serde::Serializer;
use serde::de::Error as _;
use serde::ser::Error as _;
use super::BigDecimalPayload;
pub(crate) fn serialize<S>(value: &BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
BigDecimalPayload::try_from(value)
.map_err(S::Error::custom)?
.serialize(serializer)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<BigDecimal, D::Error>
where
D: Deserializer<'de>,
{
BigDecimalPayload::deserialize(deserializer)?
.try_into()
.map_err(D::Error::custom)
}
}
#[cfg(feature = "big-decimal")]
pub(crate) mod big_decimal_vec {
use bigdecimal::BigDecimal;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serializer;
use serde::de::Error as _;
use serde::ser::Error as _;
use serde::ser::SerializeSeq;
use super::BigDecimalPayload;
pub(crate) fn serialize<S>(values: &[BigDecimal], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut sequence = serializer.serialize_seq(Some(values.len()))?;
for value in values {
let payload = BigDecimalPayload::try_from(value).map_err(S::Error::custom)?;
sequence.serialize_element(&payload)?;
}
sequence.end()
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<BigDecimal>, D::Error>
where
D: Deserializer<'de>,
{
Vec::<BigDecimalPayload>::deserialize(deserializer)?
.into_iter()
.map(|value| value.try_into().map_err(D::Error::custom))
.collect()
}
}
pub(crate) mod duration {
use std::time::Duration;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use serde::Serializer;
use serde::de::Error as _;
use super::DurationPayload;
pub(crate) fn serialize<S>(value: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
DurationPayload::from(value).serialize(serializer)
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
DurationPayload::deserialize(deserializer)?
.try_into()
.map_err(D::Error::custom)
}
}
pub(crate) mod duration_vec {
use std::time::Duration;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serializer;
use serde::de::Error as _;
use super::DurationPayload;
pub(crate) fn serialize<S>(values: &[Duration], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(values.iter().map(DurationPayload::from))
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Duration>, D::Error>
where
D: Deserializer<'de>,
{
Vec::<DurationPayload>::deserialize(deserializer)?
.into_iter()
.map(|value| value.try_into().map_err(D::Error::custom))
.collect()
}
}