geometry_dag/
local_triangle.rs1use crate::error::{DagError, DagResult};
4
5pub fn pack_local_triangle(a: u32, b: u32, c: u32) -> DagResult<u32> {
10 for (name, value) in [("a", a), ("b", b), ("c", c)] {
11 if value > 0xff {
12 return Err(DagError::invalid_input(format!(
13 "Local meshlet indices must fit in eight bits; {name} = {value}."
14 )));
15 }
16 }
17 Ok(a | (b << 8) | (c << 16))
18}
19
20pub fn unpack_local_triangle(packed: u32) -> DagResult<[u8; 3]> {
25 if packed > 0x00ff_ffff {
26 return Err(DagError::invalid_input(
27 "Packed local triangle must use only its low 24 bits.",
28 ));
29 }
30 Ok([
31 (packed & 0xff) as u8,
32 ((packed >> 8) & 0xff) as u8,
33 ((packed >> 16) & 0xff) as u8,
34 ])
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn pack_roundtrips() {
43 for a in [0u32, 1, 63, 127, 255] {
44 for b in [0u32, 42, 255] {
45 for c in [0u32, 7, 255] {
46 let packed = pack_local_triangle(a, b, c).expect("valid indices");
47 assert_eq!(unpack_local_triangle(packed).expect("valid packed"), [a as u8, b as u8, c as u8]);
48 }
49 }
50 }
51 }
52
53 #[test]
54 fn pack_rejects_out_of_range() {
55 assert!(pack_local_triangle(256, 0, 0).is_err());
56 assert!(pack_local_triangle(0, u32::MAX, 0).is_err());
57 }
58
59 #[test]
60 fn unpack_rejects_dirty_high_bits() {
61 assert!(unpack_local_triangle(0x0100_0000).is_err());
62 assert!(unpack_local_triangle(u32::MAX).is_err());
63 }
64}