dlhn 0.1.7

DLHN is a blazing fast and small data serialization format.
Documentation
use serde::{Deserialize, Serialize};
#[cfg(feature = "time")]
use time::{ext::NumericalDuration, OffsetDateTime};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct DateTime {
    unix_timestamp: i64,
    nanosecond: u32,
}

#[cfg(feature = "time")]
impl From<OffsetDateTime> for DateTime {
    fn from(date_time: OffsetDateTime) -> Self {
        Self {
            unix_timestamp: date_time.unix_timestamp(),
            nanosecond: date_time.nanosecond(),
        }
    }
}

#[cfg(feature = "time")]
impl std::convert::TryInto<OffsetDateTime> for DateTime {
    type Error = ();

    fn try_into(self) -> Result<OffsetDateTime, Self::Error> {
        OffsetDateTime::from_unix_timestamp(self.unix_timestamp)
            .map(|v| v + (self.nanosecond as i64).nanoseconds())
            .or(Err(()))
    }
}

#[cfg(feature = "time")]
#[cfg(test)]
mod tests {
    use super::DateTime;
    use crate::{Deserializer, PrefixVarint, Serializer, ZigZag};
    use serde::{Deserialize, Serialize};
    use std::convert::TryInto;
    use time::{ext::NumericalDuration, OffsetDateTime};

    #[test]
    fn from() {
        let date_time = DateTime::from(OffsetDateTime::UNIX_EPOCH);
        assert_eq!(
            date_time,
            DateTime {
                unix_timestamp: 0,
                nanosecond: 0
            }
        );
    }

    #[test]
    fn try_into() {
        let date_time = DateTime::from(OffsetDateTime::UNIX_EPOCH);
        let offset_date_time: OffsetDateTime = date_time.try_into().unwrap();
        assert_eq!(offset_date_time, OffsetDateTime::UNIX_EPOCH);
    }

    #[test]
    fn serialize() {
        fn assert_date_time(date_time: OffsetDateTime) {
            assert_eq!(
                encode_date_time(DateTime::from(date_time)),
                [
                    date_time
                        .unix_timestamp()
                        .encode_zigzag()
                        .encode_prefix_varint_vec(),
                    date_time.nanosecond().encode_prefix_varint_vec()
                ]
                .concat()
            );
        }

        IntoIterator::into_iter([
            OffsetDateTime::UNIX_EPOCH,
            OffsetDateTime::UNIX_EPOCH + 1.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 999999999.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 1000000000.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH - 100000.days(),
            OffsetDateTime::UNIX_EPOCH + 100000.days(),
            OffsetDateTime::UNIX_EPOCH - 100000.days() - 999999999.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 100000.days() + 1.nanoseconds(),
        ])
        .for_each(assert_date_time);

        assert_eq!(
            encode_date_time(DateTime::from(
                OffsetDateTime::UNIX_EPOCH + 1000000000.nanoseconds()
            )),
            encode_date_time(DateTime::from(OffsetDateTime::UNIX_EPOCH + 1.seconds()))
        );
    }

    #[test]
    fn deserialize() {
        fn assert_date_time(date_time: OffsetDateTime) {
            let buf = encode_date_time(DateTime::from(date_time));
            let mut reader = buf.as_slice();
            let mut deserializer = Deserializer::new(&mut reader);
            let result = DateTime::deserialize(&mut deserializer).unwrap();
            assert_eq!(result, DateTime::from(date_time));
        }

        IntoIterator::into_iter([
            OffsetDateTime::UNIX_EPOCH,
            OffsetDateTime::UNIX_EPOCH + 1.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 999999999.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 1000000000.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH - 100000.days(),
            OffsetDateTime::UNIX_EPOCH + 100000.days(),
            OffsetDateTime::UNIX_EPOCH - 100000.days() - 999999999.nanoseconds(),
            OffsetDateTime::UNIX_EPOCH + 100000.days() + 1.nanoseconds(),
        ])
        .for_each(assert_date_time);
    }

    fn encode_date_time(date_time: DateTime) -> Vec<u8> {
        let mut buf = Vec::new();
        let mut serializer = Serializer::new(&mut buf);
        date_time.serialize(&mut serializer).unwrap();
        buf
    }
}