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}