users/
identifiers.rs

1use core::ops::{Add, AddAssign};
2
3pub type UserIdentifierInner = u16;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
6#[repr(transparent)]
7pub struct UserIdentifier(UserIdentifierInner);
8
9impl UserIdentifier {
10    pub const ROOT: Self = Self::new(0);
11
12    pub const MINIMUM: Self = Self::new(1);
13    pub const MAXIMUM: Self = Self::new(UserIdentifierInner::MAX);
14
15    pub const fn new(identifier: UserIdentifierInner) -> Self {
16        Self(identifier)
17    }
18
19    pub const fn as_u16(self) -> UserIdentifierInner {
20        self.0
21    }
22}
23
24impl AddAssign<UserIdentifierInner> for UserIdentifier {
25    fn add_assign(&mut self, other: UserIdentifierInner) {
26        self.0 += other;
27    }
28}
29
30impl Add<UserIdentifierInner> for UserIdentifier {
31    type Output = Self;
32
33    fn add(self, other: UserIdentifierInner) -> Self {
34        Self::new(self.0 + other)
35    }
36}
37
38impl From<UserIdentifierInner> for UserIdentifier {
39    fn from(value: UserIdentifierInner) -> Self {
40        UserIdentifier::new(value)
41    }
42}
43impl From<UserIdentifier> for UserIdentifierInner {
44    fn from(value: UserIdentifier) -> Self {
45        value.as_u16()
46    }
47}
48
49pub type GroupIdentifierInner = u16;
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
52#[repr(transparent)]
53pub struct GroupIdentifier(GroupIdentifierInner);
54
55impl GroupIdentifier {
56    pub const ROOT: Self = Self::new(0);
57
58    pub const MINIMUM: Self = Self::new(1);
59    pub const MAXIMUM: Self = Self::new(GroupIdentifierInner::MAX);
60
61    pub const fn new(identifier: GroupIdentifierInner) -> Self {
62        Self(identifier)
63    }
64
65    pub const fn as_u16(self) -> GroupIdentifierInner {
66        self.0
67    }
68}
69
70impl From<GroupIdentifierInner> for GroupIdentifier {
71    fn from(value: GroupIdentifierInner) -> Self {
72        GroupIdentifier::new(value)
73    }
74}
75impl From<GroupIdentifier> for GroupIdentifierInner {
76    fn from(value: GroupIdentifier) -> Self {
77        value.as_u16()
78    }
79}
80
81impl AddAssign<GroupIdentifierInner> for GroupIdentifier {
82    fn add_assign(&mut self, other: GroupIdentifierInner) {
83        self.0 += other;
84    }
85}
86
87impl Add<GroupIdentifierInner> for GroupIdentifier {
88    type Output = Self;
89
90    fn add(self, other: GroupIdentifierInner) -> Self {
91        Self::new(self.0 + other)
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    use alloc::{collections::BTreeMap, format};
100
101    #[test]
102    fn test_user_identifier_constants() {
103        assert_eq!(UserIdentifier::ROOT.as_u16(), 0);
104        assert_eq!(UserIdentifier::MINIMUM.as_u16(), 1);
105        assert_eq!(UserIdentifier::MAXIMUM.as_u16(), u16::MAX);
106    }
107
108    #[test]
109    fn test_user_identifier_new() {
110        let id = UserIdentifier::new(42);
111        assert_eq!(id.as_u16(), 42);
112    }
113
114    #[test]
115    fn test_user_identifier_as_u16() {
116        let id = UserIdentifier::new(123);
117        assert_eq!(id.as_u16(), 123);
118    }
119
120    #[test]
121    fn test_user_identifier_add_assign() {
122        let mut id = UserIdentifier::new(10);
123        id += 5;
124        assert_eq!(id.as_u16(), 15);
125    }
126
127    #[test]
128    fn test_user_identifier_add() {
129        let id1 = UserIdentifier::new(10);
130        let id2 = id1 + 5;
131        assert_eq!(id1.as_u16(), 10); // Original unchanged
132        assert_eq!(id2.as_u16(), 15);
133    }
134
135    #[test]
136    fn test_user_identifier_from_u16() {
137        let id: UserIdentifier = 42u16.into();
138        assert_eq!(id.as_u16(), 42);
139    }
140
141    #[test]
142    fn test_user_identifier_to_u16() {
143        let id = UserIdentifier::new(42);
144        let value: u16 = id.into();
145        assert_eq!(value, 42);
146    }
147
148    #[test]
149    fn test_user_identifier_clone_copy() {
150        let id1 = UserIdentifier::new(42);
151        let id2 = id1; // Copy
152        let id3 = id1; // Copy (Clone not needed for Copy types)
153
154        assert_eq!(id1.as_u16(), 42);
155        assert_eq!(id2.as_u16(), 42);
156        assert_eq!(id3.as_u16(), 42);
157    }
158
159    #[test]
160    fn test_user_identifier_equality() {
161        let id1 = UserIdentifier::new(42);
162        let id2 = UserIdentifier::new(42);
163        let id3 = UserIdentifier::new(43);
164
165        assert_eq!(id1, id2);
166        assert_ne!(id1, id3);
167    }
168
169    #[test]
170    fn test_user_identifier_ordering() {
171        let id1 = UserIdentifier::new(10);
172        let id2 = UserIdentifier::new(20);
173
174        assert!(id1 < id2);
175        assert!(id2 > id1);
176        assert!(id1 <= id2);
177        assert!(id2 >= id1);
178        assert!(id1 <= id1);
179        assert!(id1 >= id1);
180    }
181
182    #[test]
183    fn test_group_identifier_constants() {
184        assert_eq!(GroupIdentifier::ROOT.as_u16(), 0);
185        assert_eq!(GroupIdentifier::MINIMUM.as_u16(), 1);
186        assert_eq!(GroupIdentifier::MAXIMUM.as_u16(), u16::MAX);
187    }
188
189    #[test]
190    fn test_group_identifier_new() {
191        let id = GroupIdentifier::new(42);
192        assert_eq!(id.as_u16(), 42);
193    }
194
195    #[test]
196    fn test_group_identifier_as_u16() {
197        let id = GroupIdentifier::new(123);
198        assert_eq!(id.as_u16(), 123);
199    }
200
201    #[test]
202    fn test_group_identifier_add_assign() {
203        let mut id = GroupIdentifier::new(10);
204        id += 5;
205        assert_eq!(id.as_u16(), 15);
206    }
207
208    #[test]
209    fn test_group_identifier_add() {
210        let id1 = GroupIdentifier::new(10);
211        let id2 = id1 + 5;
212        assert_eq!(id1.as_u16(), 10); // Original unchanged
213        assert_eq!(id2.as_u16(), 15);
214    }
215
216    #[test]
217    fn test_group_identifier_from_u16() {
218        let id: GroupIdentifier = 42u16.into();
219        assert_eq!(id.as_u16(), 42);
220    }
221
222    #[test]
223    fn test_group_identifier_to_u16() {
224        let id = GroupIdentifier::new(42);
225        let value: u16 = id.into();
226        assert_eq!(value, 42);
227    }
228
229    #[test]
230    fn test_group_identifier_clone_copy() {
231        let id1 = GroupIdentifier::new(42);
232        let id2 = id1; // Copy
233        let id3 = id1; // Copy (Clone not needed for Copy types)
234
235        assert_eq!(id1.as_u16(), 42);
236        assert_eq!(id2.as_u16(), 42);
237        assert_eq!(id3.as_u16(), 42);
238    }
239
240    #[test]
241    fn test_group_identifier_equality() {
242        let id1 = GroupIdentifier::new(42);
243        let id2 = GroupIdentifier::new(42);
244        let id3 = GroupIdentifier::new(43);
245
246        assert_eq!(id1, id2);
247        assert_ne!(id1, id3);
248    }
249
250    #[test]
251    fn test_group_identifier_ordering() {
252        let id1 = GroupIdentifier::new(10);
253        let id2 = GroupIdentifier::new(20);
254
255        assert!(id1 < id2);
256        assert!(id2 > id1);
257        assert!(id1 <= id2);
258        assert!(id2 >= id1);
259        assert!(id1 <= id1);
260        assert!(id1 >= id1);
261    }
262
263    #[test]
264    fn test_edge_cases_user_identifier() {
265        // Test minimum value
266        let min_id = UserIdentifier::new(0);
267        assert_eq!(min_id.as_u16(), 0);
268
269        // Test maximum value
270        let max_id = UserIdentifier::new(u16::MAX);
271        assert_eq!(max_id.as_u16(), u16::MAX);
272
273        // Test overflow behavior (this will wrap around in debug mode)
274        let near_max = UserIdentifier::new(u16::MAX - 1);
275        let result = near_max + 1;
276        assert_eq!(result.as_u16(), u16::MAX);
277    }
278
279    #[test]
280    fn test_edge_cases_group_identifier() {
281        // Test minimum value
282        let min_id = GroupIdentifier::new(0);
283        assert_eq!(min_id.as_u16(), 0);
284
285        // Test maximum value
286        let max_id = GroupIdentifier::new(u16::MAX);
287        assert_eq!(max_id.as_u16(), u16::MAX);
288
289        // Test overflow behavior (this will wrap around in debug mode)
290        let near_max = GroupIdentifier::new(u16::MAX - 1);
291        let result = near_max + 1;
292        assert_eq!(result.as_u16(), u16::MAX);
293    }
294
295    #[test]
296    fn test_hash_consistency() {
297        let mut user_map = BTreeMap::new();
298        let mut group_map = BTreeMap::new();
299
300        let user_id = UserIdentifier::new(42);
301        let group_id = GroupIdentifier::new(42);
302
303        user_map.insert(user_id, "test_user");
304        group_map.insert(group_id, "test_group");
305
306        assert_eq!(user_map.get(&user_id), Some(&"test_user"));
307        assert_eq!(group_map.get(&group_id), Some(&"test_group"));
308    }
309
310    #[test]
311    fn test_debug_format() {
312        let user_id = UserIdentifier::new(42);
313        let group_id = GroupIdentifier::new(42);
314
315        let user_debug = format!("{user_id:?}");
316        let group_debug = format!("{group_id:?}");
317
318        assert!(user_debug.contains("42"));
319        assert!(group_debug.contains("42"));
320    }
321}