Skip to main content

tlb_ton/
timestamp.rs

1use jiff::Timestamp;
2use tlb::{
3    Error,
4    bits::{
5        de::{BitReader, BitReaderExt, BitUnpackAs},
6        ser::{BitPackAs, BitWriter, BitWriterExt},
7    },
8};
9
10/// Adapter to **de**/**ser**ialize UNIX timestamp as `u32` from [`DateTime`]
11pub struct UnixTimestampSeconds;
12
13impl BitPackAs<Timestamp> for UnixTimestampSeconds {
14    type Args = ();
15
16    #[inline]
17    fn pack_as<W>(source: &Timestamp, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
18    where
19        W: BitWriter + ?Sized,
20    {
21        let timestamp: u32 = source
22            .as_second()
23            .try_into()
24            .map_err(|_| Error::custom("timestamp: overflow"))?;
25        writer.pack(timestamp, ())?;
26        Ok(())
27    }
28}
29
30impl<'de> BitUnpackAs<'de, Timestamp> for UnixTimestampSeconds {
31    type Args = ();
32
33    #[inline]
34    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<Timestamp, R::Error>
35    where
36        R: BitReader<'de> + ?Sized,
37    {
38        let timestamp: u32 = reader.unpack(())?;
39        Timestamp::from_second(timestamp as i64).map_err(Error::custom)
40    }
41}
42
43#[cfg(feature = "arbitrary")]
44const _: () = {
45    use arbitrary::{Result, Unstructured};
46    use arbitrary_with::ArbitraryAs;
47
48    impl<'a> ArbitraryAs<'a, Timestamp> for UnixTimestampSeconds {
49        fn arbitrary_as(u: &mut Unstructured<'a>) -> Result<Timestamp> {
50            Ok(Timestamp::from_second(
51                u.int_in_range(Timestamp::UNIX_EPOCH.as_second()..=Timestamp::MAX.as_second())?,
52            )
53            .unwrap_or_else(|_| unreachable!()))
54        }
55    }
56};
57
58#[cfg(test)]
59mod tests {
60
61    use tlb::bits::{de::unpack_fully_as, ser::pack_as};
62
63    use super::*;
64
65    #[test]
66    fn unix_timestamp_serde() {
67        let ts = Timestamp::UNIX_EPOCH;
68
69        let packed = pack_as::<_, UnixTimestampSeconds>(ts, ()).unwrap();
70        let got: Timestamp = unpack_fully_as::<_, UnixTimestampSeconds>(&packed, ()).unwrap();
71
72        assert_eq!(got, ts);
73    }
74}