parry3d/shape/
feature_id.rs1#[cfg(feature = "rkyv")]
2use rkyv::{bytecheck, CheckBytes};
3
4#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10#[cfg_attr(
11 feature = "rkyv",
12 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
13 archive(as = "Self")
14)]
15#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)]
16pub enum FeatureId {
17 Vertex(u32),
19 #[cfg(feature = "dim3")]
20 Edge(u32),
22 Face(u32),
24 #[default]
27 Unknown,
28}
29
30impl FeatureId {
31 pub fn unwrap_vertex(self) -> u32 {
33 match self {
34 FeatureId::Vertex(id) => id,
35 _ => panic!("The feature id does not identify a vertex."),
36 }
37 }
38
39 #[cfg(feature = "dim3")]
41 pub fn unwrap_edge(self) -> u32 {
42 match self {
43 FeatureId::Edge(id) => id,
44 _ => panic!("The feature id does not identify an edge."),
45 }
46 }
47
48 pub fn unwrap_face(self) -> u32 {
50 match self {
51 FeatureId::Face(id) => id,
52 _ => panic!("The feature id does not identify a face."),
53 }
54 }
55}
56
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58#[cfg_attr(
59 feature = "rkyv",
60 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, CheckBytes),
61 archive(as = "Self")
62)]
63#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
64pub struct PackedFeatureId(pub u32);
66
67impl PackedFeatureId {
68 pub const UNKNOWN: Self = Self(0);
70
71 const CODE_MASK: u32 = 0x3fff_ffff;
72 const HEADER_MASK: u32 = !Self::CODE_MASK;
73 const HEADER_VERTEX: u32 = 0b01 << 30;
74 #[cfg(feature = "dim3")]
75 const HEADER_EDGE: u32 = 0b10 << 30;
76 const HEADER_FACE: u32 = 0b11 << 30;
77
78 pub fn vertex(code: u32) -> Self {
80 assert_eq!(code & Self::HEADER_MASK, 0);
81 Self(Self::HEADER_VERTEX | code)
82 }
83
84 #[cfg(feature = "dim3")]
86 pub fn edge(code: u32) -> Self {
87 assert_eq!(code & Self::HEADER_MASK, 0);
88 Self(Self::HEADER_EDGE | code)
89 }
90
91 pub fn face(code: u32) -> Self {
93 assert_eq!(code & Self::HEADER_MASK, 0);
94 Self(Self::HEADER_FACE | code)
95 }
96
97 #[cfg(feature = "dim2")]
98 pub(crate) fn vertices(code: [u32; 2]) -> [Self; 2] {
100 [Self::vertex(code[0]), Self::vertex(code[1])]
101 }
102
103 #[cfg(feature = "dim3")]
104 pub(crate) fn vertices(code: [u32; 4]) -> [Self; 4] {
106 [
107 Self::vertex(code[0]),
108 Self::vertex(code[1]),
109 Self::vertex(code[2]),
110 Self::vertex(code[3]),
111 ]
112 }
113
114 #[cfg(feature = "dim3")]
115 pub(crate) fn edges(code: [u32; 4]) -> [Self; 4] {
117 [
118 Self::edge(code[0]),
119 Self::edge(code[1]),
120 Self::edge(code[2]),
121 Self::edge(code[3]),
122 ]
123 }
124
125 pub fn unpack(self) -> FeatureId {
127 let header = self.0 & Self::HEADER_MASK;
128 let code = self.0 & Self::CODE_MASK;
129 match header {
130 Self::HEADER_VERTEX => FeatureId::Vertex(code),
131 #[cfg(feature = "dim3")]
132 Self::HEADER_EDGE => FeatureId::Edge(code),
133 Self::HEADER_FACE => FeatureId::Face(code),
134 _ => FeatureId::Unknown,
135 }
136 }
137
138 pub fn is_face(self) -> bool {
140 self.0 & Self::HEADER_MASK == Self::HEADER_FACE
141 }
142
143 pub fn is_vertex(self) -> bool {
145 self.0 & Self::HEADER_MASK == Self::HEADER_VERTEX
146 }
147
148 #[cfg(feature = "dim3")]
150 pub fn is_edge(self) -> bool {
151 self.0 & Self::HEADER_MASK == Self::HEADER_EDGE
152 }
153
154 pub fn is_unknown(self) -> bool {
156 self == Self::UNKNOWN
157 }
158}
159
160impl From<FeatureId> for PackedFeatureId {
161 fn from(value: FeatureId) -> Self {
162 match value {
163 FeatureId::Face(fid) => Self::face(fid),
164 #[cfg(feature = "dim3")]
165 FeatureId::Edge(fid) => Self::edge(fid),
166 FeatureId::Vertex(fid) => Self::vertex(fid),
167 FeatureId::Unknown => Self::UNKNOWN,
168 }
169 }
170}