use std::fmt::Formatter; use dyn_clone::{clone_box, DynClone}; /// Possible values for an attribute // trying to keep values at 3 bytes #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serialize", serde(untagged))] #[derive(Clone, Debug, PartialEq)] #[allow(missing_docs)] pub enum AttributeValue<'a> { Text(&'a str), Float32(f32), Float64(f64), Int32(i32), Int64(i64), Uint32(u32), Uint64(u64), Bool(bool), Vec3Float(f32, f32, f32), Vec3Int(i32, i32, i32), Vec3Uint(u32, u32, u32), Vec4Float(f32, f32, f32, f32), Vec4Int(i32, i32, i32, i32), Vec4Uint(u32, u32, u32, u32), Bytes(&'a [u8]), Any(ArbitraryAttributeValue<'a>), } // todo #[allow(missing_docs)] impl<'a> AttributeValue<'a> { pub fn is_truthy(&self) -> bool { match self { AttributeValue::Text(t) => *t == "true", AttributeValue::Bool(t) => *t, _ => false, } } pub fn is_falsy(&self) -> bool { match self { AttributeValue::Text(t) => *t == "false", AttributeValue::Bool(t) => !(*t), _ => false, } } } impl<'a> std::fmt::Display for AttributeValue<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { AttributeValue::Text(a) => write!(f, "{}", a), AttributeValue::Float32(a) => write!(f, "{}", a), AttributeValue::Float64(a) => write!(f, "{}", a), AttributeValue::Int32(a) => write!(f, "{}", a), AttributeValue::Int64(a) => write!(f, "{}", a), AttributeValue::Uint32(a) => write!(f, "{}", a), AttributeValue::Uint64(a) => write!(f, "{}", a), AttributeValue::Bool(a) => write!(f, "{}", a), AttributeValue::Vec3Float(_, _, _) => todo!(), AttributeValue::Vec3Int(_, _, _) => todo!(), AttributeValue::Vec3Uint(_, _, _) => todo!(), AttributeValue::Vec4Float(_, _, _, _) => todo!(), AttributeValue::Vec4Int(_, _, _, _) => todo!(), AttributeValue::Vec4Uint(_, _, _, _) => todo!(), AttributeValue::Bytes(a) => write!(f, "{:?}", a), AttributeValue::Any(a) => write!(f, "{:?}", a), } } } #[derive(Clone, Copy)] #[allow(missing_docs)] pub struct ArbitraryAttributeValue<'a> { pub value: &'a dyn AnyClone, pub cmp: fn(&dyn AnyClone, &dyn AnyClone) -> bool, } impl PartialEq for ArbitraryAttributeValue<'_> { fn eq(&self, other: &Self) -> bool { (self.cmp)(self.value, other.value) } } impl std::fmt::Debug for ArbitraryAttributeValue<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("ArbitraryAttributeValue").finish() } } #[cfg(feature = "serialize")] impl<'a> serde::Serialize for ArbitraryAttributeValue<'a> { fn serialize(&self, _serializer: S) -> Result where S: serde::Serializer, { panic!("ArbitraryAttributeValue should not be serialized") } } #[cfg(feature = "serialize")] impl<'de, 'a> serde::Deserialize<'de> for &'a ArbitraryAttributeValue<'a> { fn deserialize(_deserializer: D) -> Result where D: serde::Deserializer<'de>, { panic!("ArbitraryAttributeValue is not deserializable!") } } #[cfg(feature = "serialize")] impl<'de, 'a> serde::Deserialize<'de> for ArbitraryAttributeValue<'a> { fn deserialize(_deserializer: D) -> Result where D: serde::Deserializer<'de>, { panic!("ArbitraryAttributeValue is not deserializable!") } } /// A clone, sync and send version of `Any` // we only need the Sync + Send bound when hot reloading is enabled #[cfg(any(feature = "hot-reload", debug_assertions))] pub trait AnyClone: std::any::Any + DynClone + Send + Sync { fn as_any(&self) -> &dyn std::any::Any; } #[cfg(not(any(feature = "hot-reload", debug_assertions)))] pub trait AnyClone: std::any::Any + DynClone { fn as_any(&self) -> &dyn std::any::Any; } #[cfg(any(feature = "hot-reload", debug_assertions))] impl AnyClone for T { fn as_any(&self) -> &dyn std::any::Any { self } } #[cfg(not(any(feature = "hot-reload", debug_assertions)))] impl AnyClone for T { fn as_any(&self) -> &dyn std::any::Any { self } } dyn_clone::clone_trait_object!(AnyClone); #[derive(Clone)] #[allow(missing_docs)] pub struct OwnedArbitraryAttributeValue { pub value: Box, pub cmp: fn(&dyn AnyClone, &dyn AnyClone) -> bool, } impl PartialEq for OwnedArbitraryAttributeValue { fn eq(&self, other: &Self) -> bool { (self.cmp)(&*self.value, &*other.value) } } impl std::fmt::Debug for OwnedArbitraryAttributeValue { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("OwnedArbitraryAttributeValue").finish() } } #[cfg(feature = "serialize")] impl serde::Serialize for OwnedArbitraryAttributeValue { fn serialize(&self, _serializer: S) -> Result where S: serde::Serializer, { panic!("OwnedArbitraryAttributeValue should not be serialized") } } #[cfg(feature = "serialize")] impl<'de> serde::Deserialize<'de> for &OwnedArbitraryAttributeValue { fn deserialize(_deserializer: D) -> Result where D: serde::Deserializer<'de>, { panic!("OwnedArbitraryAttributeValue is not deserializable!") } } #[cfg(feature = "serialize")] impl<'de> serde::Deserialize<'de> for OwnedArbitraryAttributeValue { fn deserialize(_deserializer: D) -> Result where D: serde::Deserializer<'de>, { panic!("OwnedArbitraryAttributeValue is not deserializable!") } } // todo #[allow(missing_docs)] impl<'a> AttributeValue<'a> { pub fn as_text(&self) -> Option<&'a str> { match self { AttributeValue::Text(s) => Some(s), _ => None, } } pub fn as_float32(&self) -> Option { match self { AttributeValue::Float32(f) => Some(*f), _ => None, } } pub fn as_float64(&self) -> Option { match self { AttributeValue::Float64(f) => Some(*f), _ => None, } } pub fn as_int32(&self) -> Option { match self { AttributeValue::Int32(i) => Some(*i), _ => None, } } pub fn as_int64(&self) -> Option { match self { AttributeValue::Int64(i) => Some(*i), _ => None, } } pub fn as_uint32(&self) -> Option { match self { AttributeValue::Uint32(i) => Some(*i), _ => None, } } pub fn as_uint64(&self) -> Option { match self { AttributeValue::Uint64(i) => Some(*i), _ => None, } } pub fn as_bool(&self) -> Option { match self { AttributeValue::Bool(b) => Some(*b), _ => None, } } pub fn as_vec3_float(&self) -> Option<(f32, f32, f32)> { match self { AttributeValue::Vec3Float(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec3_int(&self) -> Option<(i32, i32, i32)> { match self { AttributeValue::Vec3Int(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec3_uint(&self) -> Option<(u32, u32, u32)> { match self { AttributeValue::Vec3Uint(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec4_float(&self) -> Option<(f32, f32, f32, f32)> { match self { AttributeValue::Vec4Float(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_vec4_int(&self) -> Option<(i32, i32, i32, i32)> { match self { AttributeValue::Vec4Int(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_vec4_uint(&self) -> Option<(u32, u32, u32, u32)> { match self { AttributeValue::Vec4Uint(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_bytes(&self) -> Option<&[u8]> { match self { AttributeValue::Bytes(b) => Some(b), _ => None, } } pub fn as_any(&self) -> Option<&'a ArbitraryAttributeValue> { match self { AttributeValue::Any(a) => Some(a), _ => None, } } } /// A owned attribute value. #[derive(Debug, Clone, PartialEq)] #[cfg_attr( all(feature = "serialize"), derive(serde::Serialize, serde::Deserialize) )] #[allow(missing_docs)] pub enum OwnedAttributeValue { Text(String), Float32(f32), Float64(f64), Int32(i32), Int64(i64), Uint32(u32), Uint64(u64), Bool(bool), Vec3Float(f32, f32, f32), Vec3Int(i32, i32, i32), Vec3Uint(u32, u32, u32), Vec4Float(f32, f32, f32, f32), Vec4Int(i32, i32, i32, i32), Vec4Uint(u32, u32, u32, u32), Bytes(Vec), // TODO: support other types Any(OwnedArbitraryAttributeValue), } impl PartialEq> for OwnedAttributeValue { fn eq(&self, other: &AttributeValue<'_>) -> bool { match (self, other) { (Self::Text(l0), AttributeValue::Text(r0)) => l0 == r0, (Self::Float32(l0), AttributeValue::Float32(r0)) => l0 == r0, (Self::Float64(l0), AttributeValue::Float64(r0)) => l0 == r0, (Self::Int32(l0), AttributeValue::Int32(r0)) => l0 == r0, (Self::Int64(l0), AttributeValue::Int64(r0)) => l0 == r0, (Self::Uint32(l0), AttributeValue::Uint32(r0)) => l0 == r0, (Self::Uint64(l0), AttributeValue::Uint64(r0)) => l0 == r0, (Self::Bool(l0), AttributeValue::Bool(r0)) => l0 == r0, (Self::Vec3Float(l0, l1, l2), AttributeValue::Vec3Float(r0, r1, r2)) => { l0 == r0 && l1 == r1 && l2 == r2 } (Self::Vec3Int(l0, l1, l2), AttributeValue::Vec3Int(r0, r1, r2)) => { l0 == r0 && l1 == r1 && l2 == r2 } (Self::Vec3Uint(l0, l1, l2), AttributeValue::Vec3Uint(r0, r1, r2)) => { l0 == r0 && l1 == r1 && l2 == r2 } (Self::Vec4Float(l0, l1, l2, l3), AttributeValue::Vec4Float(r0, r1, r2, r3)) => { l0 == r0 && l1 == r1 && l2 == r2 && l3 == r3 } (Self::Vec4Int(l0, l1, l2, l3), AttributeValue::Vec4Int(r0, r1, r2, r3)) => { l0 == r0 && l1 == r1 && l2 == r2 && l3 == r3 } (Self::Vec4Uint(l0, l1, l2, l3), AttributeValue::Vec4Uint(r0, r1, r2, r3)) => { l0 == r0 && l1 == r1 && l2 == r2 && l3 == r3 } (Self::Bytes(l0), AttributeValue::Bytes(r0)) => l0 == r0, (_, _) => false, } } } impl<'a> From> for OwnedAttributeValue { fn from(attr: AttributeValue<'a>) -> Self { match attr { AttributeValue::Text(t) => OwnedAttributeValue::Text(t.to_owned()), AttributeValue::Float32(f) => OwnedAttributeValue::Float32(f), AttributeValue::Float64(f) => OwnedAttributeValue::Float64(f), AttributeValue::Int32(i) => OwnedAttributeValue::Int32(i), AttributeValue::Int64(i) => OwnedAttributeValue::Int64(i), AttributeValue::Uint32(u) => OwnedAttributeValue::Uint32(u), AttributeValue::Uint64(u) => OwnedAttributeValue::Uint64(u), AttributeValue::Bool(b) => OwnedAttributeValue::Bool(b), AttributeValue::Vec3Float(f1, f2, f3) => OwnedAttributeValue::Vec3Float(f1, f2, f3), AttributeValue::Vec3Int(f1, f2, f3) => OwnedAttributeValue::Vec3Int(f1, f2, f3), AttributeValue::Vec3Uint(f1, f2, f3) => OwnedAttributeValue::Vec3Uint(f1, f2, f3), AttributeValue::Vec4Float(f1, f2, f3, f4) => { OwnedAttributeValue::Vec4Float(f1, f2, f3, f4) } AttributeValue::Vec4Int(f1, f2, f3, f4) => OwnedAttributeValue::Vec4Int(f1, f2, f3, f4), AttributeValue::Vec4Uint(f1, f2, f3, f4) => { OwnedAttributeValue::Vec4Uint(f1, f2, f3, f4) } AttributeValue::Bytes(b) => OwnedAttributeValue::Bytes(b.to_owned()), AttributeValue::Any(a) => OwnedAttributeValue::Any(OwnedArbitraryAttributeValue { value: clone_box(a.value), cmp: a.cmp, }), } } } // todo #[allow(missing_docs)] impl OwnedAttributeValue { pub fn as_text(&self) -> Option<&str> { match self { OwnedAttributeValue::Text(s) => Some(s), _ => None, } } pub fn as_float32(&self) -> Option { match self { OwnedAttributeValue::Float32(f) => Some(*f), _ => None, } } pub fn as_float64(&self) -> Option { match self { OwnedAttributeValue::Float64(f) => Some(*f), _ => None, } } pub fn as_int32(&self) -> Option { match self { OwnedAttributeValue::Int32(i) => Some(*i), _ => None, } } pub fn as_int64(&self) -> Option { match self { OwnedAttributeValue::Int64(i) => Some(*i), _ => None, } } pub fn as_uint32(&self) -> Option { match self { OwnedAttributeValue::Uint32(i) => Some(*i), _ => None, } } pub fn as_uint64(&self) -> Option { match self { OwnedAttributeValue::Uint64(i) => Some(*i), _ => None, } } pub fn as_bool(&self) -> Option { match self { OwnedAttributeValue::Bool(b) => Some(*b), _ => None, } } pub fn as_vec3_float(&self) -> Option<(f32, f32, f32)> { match self { OwnedAttributeValue::Vec3Float(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec3_int(&self) -> Option<(i32, i32, i32)> { match self { OwnedAttributeValue::Vec3Int(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec3_uint(&self) -> Option<(u32, u32, u32)> { match self { OwnedAttributeValue::Vec3Uint(x, y, z) => Some((*x, *y, *z)), _ => None, } } pub fn as_vec4_float(&self) -> Option<(f32, f32, f32, f32)> { match self { OwnedAttributeValue::Vec4Float(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_vec4_int(&self) -> Option<(i32, i32, i32, i32)> { match self { OwnedAttributeValue::Vec4Int(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_vec4_uint(&self) -> Option<(u32, u32, u32, u32)> { match self { OwnedAttributeValue::Vec4Uint(x, y, z, w) => Some((*x, *y, *z, *w)), _ => None, } } pub fn as_bytes(&self) -> Option<&[u8]> { match self { OwnedAttributeValue::Bytes(b) => Some(b), _ => None, } } }