tessera_ui/dyn_eq.rs
1//! This module provides a workaround for dynamic equality testing of trait objects of the `DrawCommand` trait.
2
3use std::any::Any;
4
5use crate::renderer::drawer::DrawCommand;
6
7/// A trait that allows for cloning a trait object.
8pub trait DynCloneDraw {
9 /// Creates a boxed clone of the trait object.
10 fn clone_box(&self) -> Box<dyn DrawCommand>;
11}
12
13impl<T> DynCloneDraw for T
14where
15 T: DrawCommand + Clone + 'static,
16{
17 fn clone_box(&self) -> Box<dyn DrawCommand> {
18 Box::new(self.clone())
19 }
20}
21
22/// A trait that allows for dynamic equality testing of trait objects.
23///
24/// This trait provides a workaround for the fact that `PartialEq` is not object-safe.
25/// It allows types that are `PartialEq` to be compared even when they are behind
26/// a trait object by downcasting them to their concrete types.
27pub trait DynPartialEqDraw: DynCloneDraw {
28 /// Returns the object as a `&dyn Any`.
29 fn as_any(&self) -> &dyn Any;
30
31 /// Performs a dynamic equality check against another `DynPartialEqDraw` trait object.
32 fn dyn_eq(&self, other: &dyn DynPartialEqDraw) -> bool;
33}
34
35impl<T: DrawCommand + PartialEq + 'static> DynPartialEqDraw for T {
36 fn as_any(&self) -> &dyn Any {
37 self
38 }
39
40 fn dyn_eq(&self, other: &dyn DynPartialEqDraw) -> bool {
41 // Attempt to downcast the `other` trait object to the same concrete type as `self`.
42 if let Some(other_concrete) = other.as_any().downcast_ref::<T>() {
43 // If the downcast is successful, perform the actual comparison.
44 self == other_concrete
45 } else {
46 // If the types are different, they cannot be equal.
47 false
48 }
49 }
50}