propmaster 0.1.0

Properties and configurations for rust
Documentation
use std::borrow::Cow;

/**
 * Property is a wrapper around a name and a PropertyValue. It is used to represent
 * a single property of a node or relationship.
 * ## NOTE:
 * > For Real values NaN is considered equal to NaN.
 */
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Property {
    pub(crate) value: PropertyValue,
}

impl Property {
    pub fn new(value: PropertyValue) -> Self {
        Property { value }
    }

    pub fn value(&self) -> &PropertyValue {
        &self.value
    }

    pub fn set_value(&mut self, value: PropertyValue) {
        self.value = value;
    }

    pub fn stored_type(&self) -> String {
        match self.value {
            PropertyValue::Real(_) => "Real".to_string(),
            PropertyValue::Integer(_) => "Integer".to_string(),
            PropertyValue::UnsignedInteger(_) => "UnsignedInteger".to_string(),
            PropertyValue::SmallInteger(_) => "SmallInteger".to_string(),
            PropertyValue::SmallUnsignedInteger(_) => "SmallUnsignedInteger".to_string(),
            PropertyValue::ShortInteger(_) => "ShortInteger".to_string(),
            PropertyValue::ShortUnsignedInteger(_) => "ShortUnsignedInteger".to_string(),
            PropertyValue::TinyInteger(_) => "TinyInteger".to_string(),
            PropertyValue::Byte(_) => "Byte".to_string(),
            PropertyValue::Boolean(_) => "Boolean".to_string(),
            PropertyValue::Bytes(_) => "Bytes".to_string(),
            PropertyValue::String(_) => "String".to_string(),
        }
    }
}

/**
 * PropertyValue is a wrapper around the various types of values that a property can have.
 * For types with a fixed size, we use the primitive types. For types with a variable size,
 * we use references with lifetimes.
 */
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum PropertyValue {
    Real(f64),
    Integer(i64),
    UnsignedInteger(u64),
    SmallInteger(i32),
    SmallUnsignedInteger(u32),
    ShortInteger(i16),
    ShortUnsignedInteger(u16),
    TinyInteger(i8),
    Byte(u8),
    Boolean(bool),
    Bytes(Cow<'static, [u8]>),
    String(String),
}

impl PropertyValue {
    pub fn new<T>(v: T) -> Self
        where
            T: Into<Self>,
    {
        v.into()
    }

    pub fn new_bytes(v: &'static [u8]) -> Self {
        PropertyValue::Bytes(Cow::Borrowed(v))
    }
}

impl PartialEq for PropertyValue {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (PropertyValue::Real(a), PropertyValue::Real(b)) => a == b || a.is_nan() && b.is_nan(),
            (PropertyValue::Integer(a), PropertyValue::Integer(b)) => a == b,
            (PropertyValue::UnsignedInteger(a), PropertyValue::UnsignedInteger(b)) => a == b,
            (PropertyValue::SmallInteger(a), PropertyValue::SmallInteger(b)) => a == b,
            (PropertyValue::SmallUnsignedInteger(a), PropertyValue::SmallUnsignedInteger(b)) => {
                a == b
            }
            (PropertyValue::ShortInteger(a), PropertyValue::ShortInteger(b)) => a == b,
            (PropertyValue::ShortUnsignedInteger(a), PropertyValue::ShortUnsignedInteger(b)) => {
                a == b
            }
            (PropertyValue::TinyInteger(a), PropertyValue::TinyInteger(b)) => a == b,
            (PropertyValue::Byte(a), PropertyValue::Byte(b)) => a == b,
            (PropertyValue::Boolean(a), PropertyValue::Boolean(b)) => a == b,
            (PropertyValue::Bytes(a), PropertyValue::Bytes(b)) => a == b,
            (PropertyValue::String(a), PropertyValue::String(b)) => a == b,
            _ => false,
        }
    }
}

impl Eq for PropertyValue {}

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

    #[test]
    fn test_property_value_equality() {
        assert_eq!(PropertyValue::Real(1.0), PropertyValue::Real(1.0));
        assert_eq!(PropertyValue::Real(1.0), PropertyValue::Real(1.0));
        assert_eq!(PropertyValue::Integer(1), PropertyValue::Integer(1));
        assert_eq!(
            PropertyValue::UnsignedInteger(1),
            PropertyValue::UnsignedInteger(1)
        );
        assert_eq!(
            PropertyValue::SmallInteger(1),
            PropertyValue::SmallInteger(1)
        );
        assert_eq!(
            PropertyValue::SmallUnsignedInteger(1),
            PropertyValue::SmallUnsignedInteger(1)
        );
        assert_eq!(
            PropertyValue::ShortInteger(1),
            PropertyValue::ShortInteger(1)
        );
        assert_eq!(
            PropertyValue::ShortUnsignedInteger(1),
            PropertyValue::ShortUnsignedInteger(1)
        );
        assert_eq!(PropertyValue::TinyInteger(1), PropertyValue::TinyInteger(1));
        assert_eq!(PropertyValue::Byte(1), PropertyValue::Byte(1));
        assert_eq!(PropertyValue::Boolean(true), PropertyValue::Boolean(true));
        assert_eq!(
            PropertyValue::new_bytes(&[1u8, 2, 3]),
            PropertyValue::new_bytes(&[1u8, 2, 3])
        );
        assert_eq!(
            PropertyValue::String("Hello".to_string()),
            PropertyValue::String("Hello".to_string())
        );
    }

    #[test]
    fn test_property_value_inequality() {
        assert_ne!(PropertyValue::Real(1.0), PropertyValue::Real(2.0));
        assert_ne!(PropertyValue::Real(1.0), PropertyValue::Real(2.0));
        assert_ne!(PropertyValue::Integer(1), PropertyValue::Integer(2));
        assert_ne!(
            PropertyValue::UnsignedInteger(1),
            PropertyValue::UnsignedInteger(2)
        );
        assert_ne!(
            PropertyValue::SmallInteger(1),
            PropertyValue::SmallInteger(2)
        );
        assert_ne!(
            PropertyValue::SmallUnsignedInteger(1),
            PropertyValue::SmallUnsignedInteger(2)
        );
        assert_ne!(
            PropertyValue::ShortInteger(1),
            PropertyValue::ShortInteger(2)
        );
        assert_ne!(
            PropertyValue::ShortUnsignedInteger(1),
            PropertyValue::ShortUnsignedInteger(2)
        );
        assert_ne!(PropertyValue::TinyInteger(1), PropertyValue::TinyInteger(2));
        assert_ne!(PropertyValue::Byte(1), PropertyValue::Byte(2));
        assert_ne!(PropertyValue::Boolean(true), PropertyValue::Boolean(false));
        assert_ne!(
            PropertyValue::new_bytes(&[1u8, 2, 3]),
            PropertyValue::new_bytes(&[1u8, 2, 4])
        );
        assert_ne!(
            PropertyValue::String("Hello".to_string()),
            PropertyValue::String("World".to_string())
        );
    }
}