use serde::{de::Visitor, Deserialize, Serialize};
use std::{
marker::PhantomData,
ops::{Deref, DerefMut},
result::Result,
};
pub mod object_id {
use crate::{macros::serde_conv_doc, oid::ObjectId};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
serde_conv_doc!(
pub AsHexString,
ObjectId,
|oid: &ObjectId| -> Result<String, String> {
Ok(oid.to_hex())
},
|hex: String| -> Result<ObjectId, String> {
ObjectId::parse_str(&hex).map_err(|e| format!("Invalid ObjectId string, {}: {}", hex, e))
}
);
serde_conv_doc!(
pub FromHexString,
String,
|hex: &String| -> Result<ObjectId, String> {
ObjectId::parse_str(hex).map_err(|e| format!("Invalid ObjectId string, {}: {}", hex, e))
},
|oid: ObjectId| -> Result<String, String> {
Ok(oid.to_hex())
}
);
}
pub mod datetime {
use crate::{macros::serde_conv_doc, DateTime};
#[cfg(feature = "chrono-0_4")]
use chrono::Utc;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
serde_conv_doc!(
pub AsRfc3339String,
DateTime,
|date: &DateTime| -> Result<String, String> {
date.try_to_rfc3339_string().map_err(|e| {
format!("Cannot format DateTime {} as RFC 3339 string: {}", date, e)
})
},
|string: String| -> Result<DateTime, String> {
DateTime::parse_rfc3339_str(&string).map_err(|e| format!("Cannot format RFC 3339 string {} as DateTime: {}", string, e))
}
);
serde_conv_doc!(
pub FromRfc3339String,
String,
|string: &String| -> Result<DateTime, String> {
DateTime::parse_rfc3339_str(string).map_err(|e| format!("Cannot format RFC 3339 string {} as DateTime: {}", string, e))
},
|date: DateTime| -> Result<String, String> {
date.try_to_rfc3339_string().map_err(|e| {
format!("Cannot format DateTime {} as RFC 3339 string: {}", date, e)
})
}
);
serde_conv_doc!(
pub FromI64,
i64,
|value: &i64| -> Result<DateTime, String> {
Ok(DateTime::from_millis(*value))
},
|date: DateTime| -> Result<i64, String> {
Ok(date.timestamp_millis())
}
);
#[cfg(feature = "chrono-0_4")]
serde_conv_doc!(
pub FromChrono04DateTime,
chrono::DateTime<Utc>,
|chrono_date: &chrono::DateTime<Utc>| -> Result<DateTime, String> {
Ok(DateTime::from_chrono(*chrono_date))
},
|bson_date: DateTime| -> Result<chrono::DateTime<Utc>, String> {
Ok(bson_date.to_chrono())
}
);
#[cfg(feature = "jiff-0_2")]
serde_conv_doc!(
pub FromJiff02Timestamp,
jiff::Timestamp,
|jiff_ts: &jiff::Timestamp| -> Result<DateTime, String> {
Ok(DateTime::from_jiff(*jiff_ts))
},
|bson_date: DateTime| -> Result<jiff::Timestamp, String> {
Ok(bson_date.to_jiff())
}
);
#[cfg(feature = "time-0_3")]
serde_conv_doc!(
pub FromTime03OffsetDateTime,
time::OffsetDateTime,
|value: &time::OffsetDateTime| -> Result<DateTime, String> {
Ok(DateTime::from_time_0_3(*value))
},
|date: DateTime| -> Result<time::OffsetDateTime, String> {
Ok(date.to_time_0_3())
}
);
}
pub mod timestamp {
use crate::{macros::serde_conv_doc, Timestamp};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
serde_conv_doc!(
pub AsU32,
Timestamp,
|timestamp: &Timestamp| -> Result<u32, String> {
if timestamp.increment != 0 {
return Err(format!("Cannot convert Timestamp with a non-zero increment to u32: {:?}", timestamp));
}
Ok(timestamp.time)
},
|value: u32| -> Result<Timestamp, String> {
Ok(Timestamp { time: value, increment: 0 })
}
);
serde_conv_doc!(
pub FromU32,
u32,
|value: &u32| -> Result<Timestamp, String> {
Ok(Timestamp { time: *value, increment: 0 })
},
|timestamp: Timestamp| -> Result<u32, String> {
if timestamp.increment != 0 {
return Err(format!("Cannot convert Timestamp with a non-zero increment to u32: {:?}", timestamp));
}
Ok(timestamp.time)
}
);
}
pub mod u32 {
use crate::macros::serde_conv_doc;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
serde_conv_doc!(
pub AsF64,
u32,
|value: &u32| -> Result<f64, String> {
Ok(f64::from(*value))
},
|value: f64| -> Result<u32, String> {
if (value - value as u32 as f64).abs() <= f64::EPSILON {
Ok(value as u32)
} else {
Err(format!("Cannot convert f64 {} to u32", value))
}
}
);
serde_conv_doc!(
pub AsI32,
u32,
|value: &u32| -> Result<i32, String> {
i32::try_from(*value).map_err(|e| format!("Cannot convert u32 {} to i32: {}", value, e))
},
|value: i32| -> Result<u32, String> {
u32::try_from(value).map_err(|e| format!("Cannot convert i32 {} to u32: {}", value, e))
}
);
serde_conv_doc!(
pub AsI64,
u32,
|value: &u32| -> Result<i64, String> {
Ok(i64::from(*value))
},
|value: i64| -> Result<u32, String> {
u32::try_from(value).map_err(|e| format!("Cannot convert i64 {} to u32: {}", value, e))
}
);
}
pub mod u64 {
use crate::macros::serde_conv_doc;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
serde_conv_doc!(
pub AsF64,
u64,
|value: &u64| -> Result<f64, String> {
if value < &u64::MAX && *value == *value as f64 as u64 {
Ok(*value as f64)
} else {
Err(format!("Cannot convert u64 {} to f64", value))
}
},
|value: f64| -> Result<u64, String> {
if (value - value as u64 as f64).abs() <= f64::EPSILON {
Ok(value as u64)
} else {
Err(format!("Cannot convert f64 {} to u64", value))
}
}
);
serde_conv_doc!(
pub AsI32,
u64,
|value: &u64| -> Result<i32, String> {
i32::try_from(*value).map_err(|e| format!("Cannot convert u64 {} to i32: {}", value, e))
},
|value: i32| -> Result<u64, String> {
u64::try_from(value).map_err(|e| format!("Cannot convert i32 {} to u64: {}", value, e))
}
);
serde_conv_doc!(
pub AsI64,
u64,
|value: &u64| -> Result<i64, String> {
i64::try_from(*value).map_err(|e| format!("Cannot convert u64 {} to i64: {}", value, e))
},
|value: i64| -> Result<u64, String> {
u64::try_from(value).map_err(|e| format!("Cannot convert i64 {} to u64: {}", value, e))
}
);
}
#[cfg(feature = "uuid-1")]
pub mod uuid_1 {
use crate::macros::serde_conv_doc;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use uuid::Uuid;
serde_conv_doc!(
pub FromBson,
crate::Uuid,
|bson_uuid: &crate::Uuid| -> Result<Uuid, String> {
Ok((*bson_uuid).into())
},
|uuid: Uuid| -> Result<crate::Uuid, String> {
Ok(crate::Uuid::from(uuid))
}
);
serde_conv_doc!(
pub AsBinary,
Uuid,
|uuid: &Uuid| -> Result<crate::uuid::Uuid, String> {
Ok(crate::uuid::Uuid::from(*uuid))
},
|bson_uuid: crate::uuid::Uuid| -> Result<Uuid, String> {
Ok(bson_uuid.into())
}
);
serde_conv_doc!(
pub AsCSharpLegacyBinary,
Uuid,
|uuid: &Uuid| -> Result<crate::Binary, String> {
let inner = crate::uuid::Uuid::from(*uuid);
Ok(crate::Binary::from_uuid_with_representation(
inner,
crate::uuid::UuidRepresentation::CSharpLegacy,
))
},
|binary: crate::Binary| -> Result<Uuid, String> {
let inner = binary
.to_uuid_with_representation(crate::uuid::UuidRepresentation::CSharpLegacy)
.map_err(|e| e.to_string())?;
Ok(inner.into())
}
);
serde_conv_doc!(
pub AsJavaLegacyBinary,
Uuid,
|uuid: &Uuid| -> Result<crate::Binary, String> {
let inner = crate::uuid::Uuid::from(*uuid);
Ok(crate::Binary::from_uuid_with_representation(
inner,
crate::uuid::UuidRepresentation::JavaLegacy,
))
},
|binary: crate::Binary| -> Result<Uuid, String> {
let inner = binary
.to_uuid_with_representation(crate::uuid::UuidRepresentation::JavaLegacy)
.map_err(|e| e.to_string())?;
Ok(inner.into())
}
);
serde_conv_doc!(
pub AsPythonLegacyBinary,
Uuid,
|uuid: &Uuid| -> Result<crate::Binary, String> {
let inner = crate::uuid::Uuid::from(*uuid);
Ok(crate::Binary::from_uuid_with_representation(
inner,
crate::uuid::UuidRepresentation::PythonLegacy,
))
},
|binary: crate::Binary| -> Result<Uuid, String> {
let inner = binary
.to_uuid_with_representation(crate::uuid::UuidRepresentation::PythonLegacy)
.map_err(|e| e.to_string())?;
Ok(inner.into())
}
);
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
#[repr(transparent)]
pub struct HumanReadable<T>(pub T);
pub(crate) const HUMAN_READABLE_NEWTYPE: &str = "$__bson_private_human_readable";
impl<T: Serialize> Serialize for HumanReadable<T> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_newtype_struct(HUMAN_READABLE_NEWTYPE, &self.0)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for HumanReadable<T> {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct V<T>(PhantomData<fn() -> T>);
impl<'de, T: Deserialize<'de>> Visitor<'de> for V<T> {
type Value = HumanReadable<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("HumanReadable wrapper")
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(HumanReadable)
}
}
deserializer.deserialize_newtype_struct(HUMAN_READABLE_NEWTYPE, V(PhantomData))
}
}
impl<T: std::fmt::Display> std::fmt::Display for HumanReadable<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<T> From<T> for HumanReadable<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<T> Deref for HumanReadable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for HumanReadable<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T, R> AsRef<R> for HumanReadable<T>
where
R: ?Sized,
<HumanReadable<T> as Deref>::Target: AsRef<R>,
{
fn as_ref(&self) -> &R {
self.deref().as_ref()
}
}
impl<T, R: ?Sized> AsMut<R> for HumanReadable<T>
where
<HumanReadable<T> as Deref>::Target: AsMut<R>,
{
fn as_mut(&mut self) -> &mut R {
self.deref_mut().as_mut()
}
}