rs-firebase-admin-sdk 4.3.0

Firebase Admin SDK for Rust
Documentation
use serde::de::{self, Visitor};
use std::fmt;
use time::OffsetDateTime;

#[derive(Debug, Clone)]
pub struct StrEpochMs {
    dt: OffsetDateTime,
}

impl From<OffsetDateTime> for StrEpochMs {
    fn from(dt: OffsetDateTime) -> Self {
        Self { dt }
    }
}

impl From<StrEpochMs> for OffsetDateTime {
    fn from(value: StrEpochMs) -> Self {
        value.dt
    }
}

struct StrEpochMsVisitor;

impl Visitor<'_> for StrEpochMsVisitor {
    type Value = StrEpochMs;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a string containing count of miliseconds since UNIX epoch")
    }

    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        let unix_ts_ms: i128 = value.parse().map_err(|e| E::custom(format!("{e:?}")))?;

        let off_dt = OffsetDateTime::from_unix_timestamp_nanos(unix_ts_ms * 1000000)
            .map_err(|e| E::custom(format!("{e:?}")))?;

        Ok(off_dt.into())
    }
}

impl<'de> de::Deserialize<'de> for StrEpochMs {
    fn deserialize<D>(deserializer: D) -> Result<StrEpochMs, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        deserializer.deserialize_str(StrEpochMsVisitor)
    }
}

#[derive(Debug, Clone)]
pub struct StrEpochSec {
    dt: OffsetDateTime,
}

impl From<OffsetDateTime> for StrEpochSec {
    fn from(dt: OffsetDateTime) -> Self {
        Self { dt }
    }
}

impl From<StrEpochSec> for OffsetDateTime {
    fn from(value: StrEpochSec) -> Self {
        value.dt
    }
}

struct StrEpochSecVisitor;

impl Visitor<'_> for StrEpochSecVisitor {
    type Value = StrEpochSec;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a string containing count of seconds since UNIX epoch")
    }

    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        let unix_ts: i64 = value.parse().map_err(|e| E::custom(format!("{e:?}")))?;

        let off_dt = OffsetDateTime::from_unix_timestamp(unix_ts)
            .map_err(|e| E::custom(format!("{e:?}")))?;

        Ok(off_dt.into())
    }
}

impl<'de> de::Deserialize<'de> for StrEpochSec {
    fn deserialize<D>(deserializer: D) -> Result<StrEpochSec, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        deserializer.deserialize_str(StrEpochSecVisitor)
    }
}

#[derive(Debug, Clone)]
pub struct I128EpochMs {
    dt: OffsetDateTime,
}

impl From<OffsetDateTime> for I128EpochMs {
    fn from(dt: OffsetDateTime) -> Self {
        Self { dt }
    }
}

impl From<I128EpochMs> for OffsetDateTime {
    fn from(value: I128EpochMs) -> Self {
        value.dt
    }
}

struct I128EpochMsVisitor;

impl Visitor<'_> for I128EpochMsVisitor {
    type Value = I128EpochMs;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("an integer containing count of miliseconds since UNIX epoch")
    }

    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        let off_dt = OffsetDateTime::from_unix_timestamp_nanos(value * 1000000)
            .map_err(|e| E::custom(format!("{e:?}")))?;

        Ok(off_dt.into())
    }
}

impl<'de> de::Deserialize<'de> for I128EpochMs {
    fn deserialize<D>(deserializer: D) -> Result<I128EpochMs, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        deserializer.deserialize_i128(I128EpochMsVisitor)
    }
}