reliar-inbox 0.1.0

Transactional inbox deduplication: InboxStore/InboxHandler contracts, claim/complete/fail/purge semantics (no storage or transport dependency).
Documentation
//! `serde` (de)serialization for [`std::time::Duration`] as integer milliseconds — the same
//! `*_ms` shape `reliar-outbox` uses, copied rather than shared (this crate depends on
//! `reliar-core` only). Only compiled behind the `serde` feature.

#![cfg(feature = "serde")]

/// `#[serde(with = "duration_serde::optional_millis")]` on an `Option<Duration>` field.
pub(crate) mod optional_millis {
    use std::time::Duration;

    use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::Error as _};

    #[allow(
        clippy::ref_option,
        reason = "serde's `with` derive calls this as `&self.field`; the field is `Option<Duration>`"
    )]
    pub(crate) fn serialize<S: Serializer>(
        value: &Option<Duration>,
        s: S,
    ) -> Result<S::Ok, S::Error> {
        match value {
            Some(value) => {
                let ms = u64::try_from(value.as_millis()).map_err(S::Error::custom)?;

                Some(ms).serialize(s)
            }
            None => None::<u64>.serialize(s),
        }
    }

    pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
        d: D,
    ) -> Result<Option<Duration>, D::Error> {
        Ok(Option::<u64>::deserialize(d)?.map(Duration::from_millis))
    }
}