dlhn 0.1.7

DLHN is a blazing fast and small data serialization format.
Documentation
use crate::de::Error;
use bigdecimal::BigDecimal;
use num_bigint::BigInt;
use num_traits::Zero;
use serde::{
    de::{self, SeqAccess, Unexpected, Visitor},
    ser::SerializeSeq,
    Deserializer, Serializer,
};

struct BigDecimalVisitor;

impl<'de> Visitor<'de> for BigDecimalVisitor {
    type Value = BigDecimal;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str("format error")
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        let digits = BigInt::from_signed_bytes_le(
            seq.next_element::<Vec<u8>>()?
                .ok_or(de::Error::invalid_value(Unexpected::Seq, &Error::Read))?
                .as_slice(),
        );
        if digits.is_zero() {
            Ok(BigDecimal::from(digits))
        } else {
            Ok(BigDecimal::new(
                digits,
                seq.next_element::<i64>()?
                    .ok_or(de::Error::invalid_value(Unexpected::Seq, &Error::Read))?,
            ))
        }
    }
}

pub fn serialize<T: Serializer>(value: &BigDecimal, serializer: T) -> Result<T::Ok, T::Error> {
    let mut seq = serializer.serialize_seq(None)?;

    if value.is_zero() {
        seq.serialize_element(&0u8)?;
    } else {
        let (bigint, scale) = value.normalized().into_bigint_and_exponent();
        seq.serialize_element(&bigint.to_signed_bytes_le())?;
        seq.serialize_element(&scale)?;
    }

    seq.end()
}

pub fn deserialize<'de, T: Deserializer<'de>>(deserializer: T) -> Result<BigDecimal, T::Error> {
    deserializer.deserialize_tuple(2, BigDecimalVisitor)
}

#[cfg(test)]
mod tests {
    use crate::{de::Deserializer, ser::Serializer};
    use bigdecimal::BigDecimal;
    use num_bigint::BigInt;

    #[test]
    fn serilize() {
        assert_eq!(encode_big_decimal(BigDecimal::from(0)), [0]);
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), 0)),
            [1, 1, 0]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), -1)),
            [1, 1, 1]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), 1)),
            [1, 1, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(10), 0)),
            [1, 1, 1]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), 63)),
            [1, 1, 126]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), 64)),
            [1, 1, 128, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), -64)),
            [1, 1, 127]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(1), -65)),
            [1, 1, 129, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(i16::MIN), 0)),
            [2, 0, 128, 0]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::new(BigInt::from(i16::MAX), 0)),
            [2, 255, 127, 0]
        );
    }

    #[test]
    fn deserialize() {
        fn assert_big_decimal(value: BigDecimal) {
            let buf = encode_big_decimal(value.clone());
            let mut reader = buf.as_slice();
            let mut deserializer = Deserializer::new(&mut reader);
            assert_eq!(value, super::deserialize(&mut deserializer).unwrap());
        }

        IntoIterator::into_iter([
            BigDecimal::from(0),
            BigDecimal::new(BigInt::from(1), 0),
            BigDecimal::new(BigInt::from(1), -1),
            BigDecimal::new(BigInt::from(1), 1),
            BigDecimal::new(BigInt::from(1), 63),
            BigDecimal::new(BigInt::from(1), 64),
            BigDecimal::new(BigInt::from(1), -64),
            BigDecimal::new(BigInt::from(1), -65),
            BigDecimal::new(BigInt::from(i16::MIN), 0),
            BigDecimal::new(BigInt::from(i16::MAX), 0),
        ])
        .for_each(assert_big_decimal);
    }

    fn encode_big_decimal(value: BigDecimal) -> Vec<u8> {
        let mut buf = Vec::new();
        let mut serializer = Serializer::new(&mut buf);
        super::serialize(&value, &mut serializer).unwrap();
        buf
    }
}