1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! Trait-object equality and hashing for component trees.
//!
//! [`RasterComponent`](crate::raster::RasterComponent) and
//! [`VectorComponent`](crate::vector::VectorComponent) need to participate in
//! `PartialEq` and `Hash` so that render results can be memoized in a
//! `RenderContext` cache keyed by component identity. The trait-object form
//! `dyn Component` cannot derive these directly — `PartialEq::eq` is not
//! dyn-safe and `Hash::hash` is parameterised over `H: Hasher`.
//!
//! [`DynEq`] and [`DynHash`] are the standard workaround: they expose the
//! type-erased shape of `==` and `hash` via [`Any`] downcast and a
//! `&mut dyn Hasher` argument, and have blanket impls for any `T: PartialEq +
//! Hash + 'static`. A component trait adds them as super-traits, and a
//! manual `impl PartialEq for dyn Component` / `impl Hash for dyn Component`
//! delegates through them. With that wired up, `Box<dyn Component>`,
//! `Vec<Box<dyn Component>>`, etc. pick up `PartialEq + Hash` automatically
//! through the standard library blanket impls, so `#[derive]` on containers
//! that hold trait objects just works.
//!
//! [`hash_f32`] / [`hash_f32_slice`] are the canonical hashers for `f32`
//! fields and slices in cache-key types. They use `to_bits()` so `-0.0`,
//! `+0.0`, and `NaN` keep distinct hashes (matching the way `PartialEq` on
//! `f32` already treats them distinctly when sourced from bit patterns).
use Any;
use ;
/// Object-safe equality. Implemented for all `T: PartialEq + 'static`.
///
/// Used as a super-trait on `RasterComponent` / `VectorComponent` so a
/// `dyn Component` can compare itself with another `dyn Component` by
/// downcasting to its concrete type. Two trait objects of different
/// concrete types compare as not-equal.
///
/// The `dyn_eq` argument is `&dyn Any` (not `&dyn DynEq`) so callers can
/// hand it `other.as_any()` directly — this sidesteps trait-object
/// upcasting between component traits and `DynEq`.
/// Object-safe hashing. Implemented for all `T: Hash + ?Sized`.
///
/// `Hash::hash` is generic over the hasher, so `dyn Component` cannot
/// implement it directly. `DynHash` erases the hasher type behind
/// `&mut dyn Hasher`, which works because the standard library has
/// `impl<H: Hasher + ?Sized> Hasher for &mut H` — i.e. `&mut dyn Hasher`
/// is itself a `Hasher`, so calling `Hash::hash(&self, &mut state)` from
/// inside the impl is legal.
/// Hashes an `f32` by its bit pattern.
///
/// `f32` does not implement `Hash` because its `PartialEq` is not
/// reflexive (`NaN != NaN`), so the standard library refuses to derive a
/// hash that would violate `a == b => hash(a) == hash(b)`. For cache-key
/// use we want a total hash and treat equal bit patterns as equal — this
/// helper makes that intent explicit and consistent across types.
/// Hashes an `&[f32]` by hashing each element's bit pattern in order.