atproto-record 0.9.1

AT Protocol record signature operations - cryptographic signing and verification for AT Protocol records
Documentation
//! DateTime serialization utilities for AT Protocol records.
//!
//! This module provides Serde serialization and deserialization functions for DateTime<Utc>
//! values with RFC 3339 formatting, including support for optional datetime fields.
//! Used for consistent datetime handling across AT Protocol record structures.
//!
//! ## Modules
//!
//! - [`format`] - Required datetime field serialization in RFC 3339 format with milliseconds
//! - [`optional_format`] - Optional datetime field serialization handling None values

/// Required datetime field serialization in RFC 3339 format with milliseconds.
///
/// Provides serde serialization functions for DateTime<Utc> values
/// using RFC 3339 formatting with millisecond precision.
pub mod format {
    use chrono::{DateTime, SecondsFormat, Utc};
    use serde::{self, Deserialize, Deserializer, Serializer};

    /// Serializes a DateTime<Utc> to RFC 3339 format with milliseconds.
    pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let s = date.to_rfc3339_opts(SecondsFormat::Millis, true);
        serializer.serialize_str(&s)
    }

    /// Deserializes an RFC 3339 string to DateTime<Utc>.
    pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let date_value = String::deserialize(deserializer)?;
        DateTime::parse_from_rfc3339(&date_value)
            .map(|v| v.with_timezone(&Utc))
            .map_err(serde::de::Error::custom)
    }
}

/// Optional datetime field serialization handling None values.
///
/// Provides serde serialization functions for Option<DateTime<Utc>> values
/// using RFC 3339 formatting with proper None handling.
pub mod optional_format {
    use chrono::{DateTime, SecondsFormat, Utc};
    use serde::{self, Deserialize, Deserializer, Serializer};

    /// Serializes an Option<DateTime<Utc>> to RFC 3339 format with milliseconds.
    pub fn serialize<S>(date: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if date.is_none() {
            return serializer.serialize_none();
        }
        let s = date.unwrap().to_rfc3339_opts(SecondsFormat::Millis, true);
        serializer.serialize_str(&s)
    }

    /// Deserializes an optional RFC 3339 string to Option<DateTime<Utc>>.
    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let maybe_date_value: Option<String> = Option::deserialize(deserializer)?;
        if maybe_date_value.is_none() {
            return Ok(None);
        }
        let date_value = maybe_date_value.unwrap();
        DateTime::parse_from_rfc3339(&date_value)
            .map(|v| v.with_timezone(&Utc))
            .map_err(serde::de::Error::custom)
            .map(Some)
    }
}