blitz_traits/node_id.rs
1//! Versioned node identifier shared between the Blitz crates.
2
3/// A versioned identifier for a node in a Blitz DOM tree.
4///
5/// A `NodeId` packs a 32-bit slot index (low bits) and a 32-bit version
6/// (high bits). Node storage bumps a slot's version when the slot is
7/// reused, so ids referring to a dropped node no longer resolve (lookups
8/// return `None` rather than aliasing the new node occupying the slot).
9///
10/// The `Default` value is a null id which never resolves to a node.
11#[derive(Copy, Clone, Default, Eq, PartialEq, Hash)]
12pub struct NodeId(u64);
13
14impl NodeId {
15 /// Convert this id to its raw `u64` representation (index + version).
16 ///
17 /// The value round-trips through [`NodeId::from_u64`]. This is useful for
18 /// interop with APIs which use integer ids (e.g. Taffy or AccessKit).
19 #[inline(always)]
20 pub fn as_u64(self) -> u64 {
21 self.0
22 }
23
24 /// Reconstruct a `NodeId` from the raw `u64` representation produced by
25 /// [`NodeId::as_u64`].
26 ///
27 /// Passing a value that did not come from `as_u64` will produce an id
28 /// which fails to resolve (it will not alias an unrelated live node).
29 #[inline(always)]
30 pub fn from_u64(raw: u64) -> Self {
31 Self(raw)
32 }
33
34 /// The slot index part of this id.
35 #[inline(always)]
36 fn index(self) -> u32 {
37 self.0 as u32
38 }
39
40 /// The version part of this id.
41 #[inline(always)]
42 fn version(self) -> u32 {
43 (self.0 >> 32) as u32
44 }
45}
46
47/// Ordered by slot index first, then by version, so that ordering roughly
48/// matches node creation order (as with the previous `Slab`-backed storage)
49/// rather than being dominated by the version bits.
50impl Ord for NodeId {
51 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
52 (self.index(), self.version()).cmp(&(other.index(), other.version()))
53 }
54}
55
56impl PartialOrd for NodeId {
57 #[inline]
58 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63impl std::fmt::Debug for NodeId {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "NodeId({}v{})", self.index(), self.version())
66 }
67}
68
69impl std::fmt::Display for NodeId {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{:?}", self)
72 }
73}