trs-data-value 0.2.0

Data Value for common data types
Documentation
use super::DataValue;

impl PartialOrd for DataValue {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for DataValue {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        use DataValue::*;
        match (self, other) {
            (Bool(l0), Bool(r0)) => l0.cmp(r0),
            (U32(l0), U32(r0)) => l0.cmp(r0),
            (I32(l0), I32(r0)) => l0.cmp(r0),
            (U8(l0), U8(r0)) => l0.cmp(r0),
            (U64(l0), U64(r0)) => l0.cmp(r0),
            (I64(l0), I64(r0)) => l0.cmp(r0),
            (U128(l0), U128(r0)) => l0.cmp(r0),
            (I128(l0), I128(r0)) => l0.cmp(r0),
            (F32(l0), F32(r0)) => l0.partial_cmp(r0).expect("BUG: cannot compare f32"),
            (F64(l0), F64(r0)) => l0.partial_cmp(r0).expect("BUG: cannot compare f64"),
            (String(l0), String(r0)) => l0.cmp(r0),
            (Bytes(l0), Bytes(r0)) => l0.cmp(r0),
            (Vec(l0), Vec(r0)) => l0.cmp(r0),
            (Map(l0), Map(r0)) => l0.keys().cmp(r0.keys()),
            _ => std::cmp::Ordering::Less,
        }
    }
}
impl std::cmp::PartialEq for DataValue {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
            (Self::U32(l0), Self::U32(r0)) => l0 == r0,
            (Self::I32(l0), Self::I32(r0)) => l0 == r0,
            (Self::U8(l0), Self::U8(r0)) => l0 == r0,
            (Self::U64(l0), Self::U64(r0)) => l0 == r0,
            (Self::I64(l0), Self::I64(r0)) => l0 == r0,
            (Self::U128(l0), Self::U128(r0)) => l0 == r0,
            (Self::I128(l0), Self::I128(r0)) => l0 == r0,
            (Self::F32(l0), Self::F32(r0)) => (l0 - r0).abs() < f32::EPSILON,
            (Self::F64(l0), Self::F64(r0)) => (l0 - r0).abs() < f64::EPSILON,
            (Self::String(l0), Self::String(r0)) => l0 == r0,
            (Self::Bytes(l0), Self::Bytes(r0)) => l0 == r0,
            (Self::Vec(l0), Self::Vec(r0)) => l0.eq(r0),
            (Self::Map(l0), Self::Map(r0)) => l0.eq(r0),
            (Self::Null, Self::Null) => true,
            _ => false,
        }
    }
}

impl std::cmp::Eq for DataValue {}

#[cfg(test)]
mod test {
    use super::*;
    use rstest::*;

    #[rstest]
    #[case(DataValue::U8(1), DataValue::U8(1), true)]
    #[case(DataValue::U8(1), DataValue::U8(2), false)]
    #[case(DataValue::U8(1), DataValue::U32(1), false)]
    #[case(DataValue::U8(1), DataValue::I32(1), false)]
    #[case(DataValue::U8(1), DataValue::U64(1), false)]
    #[case(DataValue::U8(1), DataValue::I64(1), false)]
    #[case(DataValue::U8(1), DataValue::U128(1), false)]
    #[case(DataValue::U8(1), DataValue::I128(1), false)]
    #[case(DataValue::U8(1), DataValue::F32(1.0), false)]
    #[case(DataValue::U8(1), DataValue::F64(1.0), false)]
    #[case(DataValue::U8(1), DataValue::String("1".into()), false)]
    #[case(DataValue::U8(1), DataValue::Bytes(b"1".to_vec()), false)]
    #[case(DataValue::U8(1), DataValue::Vec(vec![1.into()]), false)]
    #[case(DataValue::U8(1), DataValue::Map(crate::stdhashmap!("a" => 1)), false)]
    #[case(DataValue::U8(1), DataValue::Null, false)]
    fn test_eq(#[case] left: DataValue, #[case] right: DataValue, #[case] expected: bool) {
        assert_eq!(left == right, expected);
        assert_eq!(left.cmp(&right), expected.cmp(&true));
    }

    #[rstest]
    #[case(DataValue::Vec(
        vec![
            DataValue::U8(1), DataValue::U32(2), DataValue::U64(3), DataValue::U128(4), DataValue::I128(5), DataValue::I32(1), DataValue::I64(1),
             DataValue::I128(5), DataValue::F32(6.0), DataValue::F64(7.0), DataValue::String("8".into()),
              DataValue::Bytes(b"9".to_vec()), DataValue::Vec(vec![DataValue::U8(10)]), 
              DataValue::Map(crate::stdhashmap!("a" => 11))
        ]
    ), DataValue::Vec(vec![
        DataValue::U8(1), DataValue::U32(2), DataValue::U64(3), DataValue::U128(4), DataValue::I128(5), DataValue::I32(1), DataValue::I64(1),
        DataValue::I128(5), DataValue::F32(6.0), DataValue::F64(7.0), DataValue::String("8".into()),
         DataValue::Bytes(b"9".to_vec()), DataValue::Vec(vec![DataValue::U8(10)]), 
         DataValue::Map(crate::stdhashmap!("a" => 11))]), std::cmp::Ordering::Equal)
    ]
    #[case(DataValue::Vec(
        vec![
            DataValue::U8(1), DataValue::U32(2), DataValue::U64(3), DataValue::U128(4), DataValue::I128(5), DataValue::I32(1), DataValue::I64(1),
             DataValue::I128(5), DataValue::F32(6.0), DataValue::F64(7.0), DataValue::String("8".into()),
              DataValue::Bytes(b"9".to_vec()), DataValue::Vec(vec![DataValue::U8(10)]), 
              DataValue::Map(crate::stdhashmap!("a" => 11))
        ]
    ), DataValue::Vec(
        vec![DataValue::U8(1), DataValue::U8(2), DataValue::U8(3)]
    ), std::cmp::Ordering::Less)
    ]
    fn test_cmp(
        #[case] left: DataValue,
        #[case] right: DataValue,
        #[case] expected: std::cmp::Ordering,
    ) {
        assert_eq!(left.cmp(&right), expected);
    }
}