dlhn 0.1.7

DLHN is a blazing fast and small data serialization format.
Documentation
use crate::de::Error;
#[cfg(feature = "num-traits")]
use num_traits::Zero;
use serde::{
    de::{self, SeqAccess, Unexpected, Visitor},
    ser::SerializeSeq,
    Deserialize, Serialize,
};

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BigDecimal {
    signed_bytes: Vec<u8>,
    scale: i64,
}

#[cfg(all(feature = "num-traits", feature = "bigdecimal"))]
impl From<bigdecimal::BigDecimal> for BigDecimal {
    fn from(v: bigdecimal::BigDecimal) -> Self {
        if v.is_zero() {
            Self {
                signed_bytes: Vec::new(),
                scale: 0,
            }
        } else {
            let (bigint, scale) = v.normalized().into_bigint_and_exponent();
            Self {
                signed_bytes: bigint.to_signed_bytes_le(),
                scale,
            }
        }
    }
}

#[cfg(all(feature = "num-traits", feature = "num-bigint", feature = "bigdecimal"))]
impl Into<bigdecimal::BigDecimal> for BigDecimal {
    fn into(self) -> bigdecimal::BigDecimal {
        bigdecimal::BigDecimal::new(
            num_bigint::BigInt::from_signed_bytes_le(self.signed_bytes.as_ref()),
            self.scale,
        )
    }
}

impl Serialize for BigDecimal {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut seq = serializer.serialize_seq(None)?;

        if self.signed_bytes == [] {
            seq.serialize_element(&0u8)?;
        } else {
            seq.serialize_element(&self.signed_bytes)?;
            seq.serialize_element(&self.scale)?;
        }

        seq.end()
    }
}

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 signed_bytes = seq
            .next_element::<Vec<u8>>()?
            .ok_or(de::Error::invalid_value(Unexpected::Seq, &Error::Read))?;
        if signed_bytes.is_empty() {
            Ok(BigDecimal {
                signed_bytes,
                scale: 0,
            })
        } else {
            let scale = seq
                .next_element::<i64>()?
                .ok_or(de::Error::invalid_value(Unexpected::Seq, &Error::Read))?;
            Ok(BigDecimal {
                signed_bytes,
                scale,
            })
        }
    }
}
impl<'de> Deserialize<'de> for BigDecimal {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_tuple(2, BigDecimalVisitor)
    }
}

#[cfg(all(feature = "num-traits", feature = "num-bigint", feature = "bigdecimal"))]
#[cfg(test)]
mod tests {
    use crate::{big_decimal::BigDecimal, de::Deserializer, ser::Serializer};
    use num_bigint::BigInt;
    use serde::{Deserialize, Serialize};

    #[test]
    fn from() {
        let v = BigDecimal::from(bigdecimal::BigDecimal::from(123));
        assert_eq!(
            v,
            BigDecimal {
                signed_bytes: vec![123],
                scale: 0,
            }
        );
    }

    #[test]
    fn into() {
        let v: bigdecimal::BigDecimal = BigDecimal::from(bigdecimal::BigDecimal::from(-123)).into();
        assert_eq!(v, bigdecimal::BigDecimal::from(-123));
    }

    #[test]
    fn serialize() {
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::from(0))),
            [0]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                0
            ))),
            [1, 1, 0]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                -1
            ))),
            [1, 1, 1]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                1
            ))),
            [1, 1, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(10),
                0
            ))),
            [1, 1, 1]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                63
            ))),
            [1, 1, 126]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                64
            ))),
            [1, 1, 128, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                -64
            ))),
            [1, 1, 127]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(1),
                -65
            ))),
            [1, 1, 129, 2]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::BigDecimal::new(
                BigInt::from(i16::MIN),
                0
            ))),
            [2, 0, 128, 0]
        );
        assert_eq!(
            encode_big_decimal(BigDecimal::from(bigdecimal::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);
            let result = BigDecimal::deserialize(&mut deserializer).unwrap();
            assert_eq!(result, value);
        }

        IntoIterator::into_iter([
            BigDecimal::from(bigdecimal::BigDecimal::from(0)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), 0)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), -1)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), 1)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), 63)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), 64)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), -64)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(1), -65)),
            BigDecimal::from(bigdecimal::BigDecimal::new(BigInt::from(i16::MIN), 0)),
            BigDecimal::from(bigdecimal::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);
        value.serialize(&mut serializer).unwrap();
        buf
    }
}