Ver código fonte

allow arbitrary attribute value in owned attribute value (#574)

Demonthos 2 anos atrás
pai
commit
928b5358b2

+ 3 - 0
packages/core/Cargo.toml

@@ -45,6 +45,9 @@ serde = { version = "1", features = ["derive"], optional = true }
 # todo: I want to get rid of this
 backtrace = "0.3"
 
+# allows cloing trait objects
+dyn-clone = "1.0.9"
+
 [features]
 default = []
 serialize = ["serde"]

+ 82 - 4
packages/core/src/arbitrary_value.rs

@@ -1,5 +1,7 @@
 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))]
@@ -74,8 +76,8 @@ impl<'a> std::fmt::Display for AttributeValue<'a> {
 #[derive(Clone, Copy)]
 #[allow(missing_docs)]
 pub struct ArbitraryAttributeValue<'a> {
-    pub value: &'a dyn std::any::Any,
-    pub cmp: fn(&'a dyn std::any::Any, &'a dyn std::any::Any) -> bool,
+    pub value: &'a dyn AnyClone,
+    pub cmp: fn(&dyn AnyClone, &dyn AnyClone) -> bool,
 }
 
 impl PartialEq for ArbitraryAttributeValue<'_> {
@@ -118,6 +120,79 @@ impl<'de, 'a> serde::Deserialize<'de> for ArbitraryAttributeValue<'a> {
     }
 }
 
+/// 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<T: std::any::Any + DynClone + Send + Sync> AnyClone for T {
+    fn as_any(&self) -> &dyn std::any::Any {
+        self
+    }
+}
+#[cfg(not(any(feature = "hot-reload", debug_assertions)))]
+impl<T: std::any::Any + DynClone> 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<dyn AnyClone>,
+    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<'a> serde::Serialize for OwnedArbitraryAttributeValue {
+    fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        panic!("OwnedArbitraryAttributeValue should not be serialized")
+    }
+}
+#[cfg(feature = "serialize")]
+impl<'de, 'a> serde::Deserialize<'de> for &'a OwnedArbitraryAttributeValue {
+    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        panic!("OwnedArbitraryAttributeValue is not deserializable!")
+    }
+}
+#[cfg(feature = "serialize")]
+impl<'de, 'a> serde::Deserialize<'de> for OwnedArbitraryAttributeValue {
+    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        panic!("OwnedArbitraryAttributeValue is not deserializable!")
+    }
+}
+
 // todo
 #[allow(missing_docs)]
 impl<'a> AttributeValue<'a> {
@@ -261,7 +336,7 @@ pub enum OwnedAttributeValue {
 
     Bytes(Vec<u8>),
     // TODO: support other types
-    // Any(ArbitraryAttributeValue<'a>),
+    Any(OwnedArbitraryAttributeValue),
 }
 
 impl PartialEq<AttributeValue<'_>> for OwnedAttributeValue {
@@ -321,7 +396,10 @@ impl<'a> From<AttributeValue<'a>> for OwnedAttributeValue {
                 OwnedAttributeValue::Vec4Uint(f1, f2, f3, f4)
             }
             AttributeValue::Bytes(b) => OwnedAttributeValue::Bytes(b.to_owned()),
-            AttributeValue::Any(_) => todo!(),
+            AttributeValue::Any(a) => OwnedAttributeValue::Any(OwnedArbitraryAttributeValue {
+                value: clone_box(a.value),
+                cmp: a.cmp,
+            }),
         }
     }
 }

+ 6 - 0
packages/core/src/template.rs

@@ -790,6 +790,12 @@ impl TemplateValue for OwnedAttributeValue {
             OwnedAttributeValue::Vec4Uint(u1, u2, u3, u4) => {
                 AttributeValue::Vec4Uint(u1, u2, u3, u4)
             }
+            OwnedAttributeValue::Any(owned) => {
+                AttributeValue::Any(crate::ArbitraryAttributeValue {
+                    value: bump.alloc(owned.value),
+                    cmp: owned.cmp,
+                })
+            }
         }
     }
 }

+ 1 - 0
packages/rsx/src/template.rs

@@ -216,6 +216,7 @@ impl ToTokens for TemplateAttributeBuilder {
                     OwnedAttributeValue::Bytes(b) => {
                         quote! {StaticAttributeValue::Bytes(&[#(#b),*])}
                     }
+                    OwnedAttributeValue::Any(_) => todo!(),
                 };
                 quote! {TemplateAttributeValue::Static(#val)}
             }