Skip to main content

axiolid_topology/
id.rs

1//! Typed arena handles prevent mixing vertex, edge, face, and shell indices.
2
3use core::fmt;
4
5macro_rules! topology_id {
6    ($name:ident, $label:literal) => {
7        #[doc = concat!("Stable handle into a B-rep ", $label, " arena.")]
8        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9        #[cfg_attr(
10            feature = "serde",
11            derive(serde::Serialize, serde::Deserialize),
12            serde(transparent)
13        )]
14        pub struct $name(u32);
15
16        impl $name {
17            pub(crate) fn from_index(index: usize) -> Self {
18                Self(u32::try_from(index).expect("topology arena exceeds u32 capacity"))
19            }
20
21            /// Zero-based arena index.
22            pub const fn index(self) -> usize {
23                self.0 as usize
24            }
25        }
26
27        impl fmt::Display for $name {
28            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29                write!(f, concat!($label, "#{}"), self.0)
30            }
31        }
32    };
33}
34
35topology_id!(VertexId, "vertex");
36topology_id!(EdgeId, "edge");
37topology_id!(LoopId, "loop");
38topology_id!(FaceId, "face");
39topology_id!(ShellId, "shell");
40topology_id!(SolidId, "solid");