Skip to main content

box2d_rust/
id.rs

1// Port of box2d-cpp-reference/include/box2d/id.h
2//
3// These ids are opaque handles to internal Box2D objects, passed by value. All
4// ids are null when zero-initialized. The store/load helpers pack and unpack a
5// handle into a plain integer; the bit layout is reproduced exactly so handles
6// round-trip identically to the C library.
7//
8// SPDX-FileCopyrightText: 2023 Erin Catto
9// SPDX-License-Identifier: MIT
10
11/// World id references a world instance. Treat as an opaque handle.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13pub struct WorldId {
14    pub index1: u16,
15    pub generation: u16,
16}
17
18/// Body id references a body instance. Treat as an opaque handle.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
20pub struct BodyId {
21    pub index1: i32,
22    pub world0: u16,
23    pub generation: u16,
24}
25
26/// Shape id references a shape instance. Treat as an opaque handle.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
28pub struct ShapeId {
29    pub index1: i32,
30    pub world0: u16,
31    pub generation: u16,
32}
33
34/// Chain id references a chain instance. Treat as an opaque handle.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
36pub struct ChainId {
37    pub index1: i32,
38    pub world0: u16,
39    pub generation: u16,
40}
41
42/// Joint id references a joint instance. Treat as an opaque handle.
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
44pub struct JointId {
45    pub index1: i32,
46    pub world0: u16,
47    pub generation: u16,
48}
49
50/// Contact id references a contact instance. Treat as an opaque handle.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
52pub struct ContactId {
53    pub index1: i32,
54    pub world0: u16,
55    pub padding: i16,
56    pub generation: u32,
57}
58
59impl WorldId {
60    /// Store a world id into a u32. (b2StoreWorldId)
61    pub fn store(self) -> u32 {
62        ((self.index1 as u32) << 16) | (self.generation as u32)
63    }
64
65    /// Load a u32 into a world id. (b2LoadWorldId)
66    pub fn load(x: u32) -> WorldId {
67        WorldId {
68            index1: (x >> 16) as u16,
69            generation: x as u16,
70        }
71    }
72
73    /// True if this id is null (index1 == 0). (B2_IS_NULL)
74    pub fn is_null(self) -> bool {
75        self.index1 == 0
76    }
77
78    /// True if this id is non-null. (B2_IS_NON_NULL)
79    pub fn is_non_null(self) -> bool {
80        self.index1 != 0
81    }
82}
83
84// Body, shape, chain, and joint ids share the same 64-bit layout, so a macro
85// generates their identical store/load/null helpers.
86macro_rules! impl_u64_id {
87    ($ty:ident) => {
88        impl $ty {
89            /// Store this id into a u64.
90            pub fn store(self) -> u64 {
91                ((self.index1 as u64) << 32)
92                    | ((self.world0 as u64) << 16)
93                    | (self.generation as u64)
94            }
95
96            /// Load a u64 into this id type.
97            pub fn load(x: u64) -> $ty {
98                $ty {
99                    index1: (x >> 32) as i32,
100                    world0: (x >> 16) as u16,
101                    generation: x as u16,
102                }
103            }
104
105            /// True if this id is null (index1 == 0). (B2_IS_NULL)
106            pub fn is_null(self) -> bool {
107                self.index1 == 0
108            }
109
110            /// True if this id is non-null. (B2_IS_NON_NULL)
111            pub fn is_non_null(self) -> bool {
112                self.index1 != 0
113            }
114        }
115    };
116}
117
118impl_u64_id!(BodyId);
119impl_u64_id!(ShapeId);
120impl_u64_id!(ChainId);
121impl_u64_id!(JointId);
122
123impl ContactId {
124    /// Store a contact id into three u32 values. (b2StoreContactId)
125    pub fn store(self) -> [u32; 3] {
126        [self.index1 as u32, self.world0 as u32, self.generation]
127    }
128
129    /// Load three u32 values into a contact id. (b2LoadContactId)
130    pub fn load(values: [u32; 3]) -> ContactId {
131        ContactId {
132            index1: values[0] as i32,
133            world0: values[1] as u16,
134            padding: 0,
135            generation: values[2],
136        }
137    }
138
139    /// True if this id is null (index1 == 0). (B2_IS_NULL)
140    pub fn is_null(self) -> bool {
141        self.index1 == 0
142    }
143
144    /// True if this id is non-null. (B2_IS_NON_NULL)
145    pub fn is_non_null(self) -> bool {
146        self.index1 != 0
147    }
148}