1#![warn(unused_crate_dependencies)]
4
5use std::fmt::{Debug, Display, Formatter};
6
7pub use uuid::*;
8
9mod uuid;
10
11#[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)]
13#[repr(transparent)]
14pub struct CompanyId(pub u16);
15
16impl CompanyId {
17 #[inline(always)]
19 #[must_use]
20 pub const fn raw(self) -> u16 {
21 self.0
22 }
23
24 #[must_use]
27 pub const fn name(self) -> Option<&'static str> {
28 let i = match self.0.checked_sub(Self::MIN) {
29 Some(0) => return Some(Self::FIRST),
30 Some(i) if (i as usize) < Self::IDX.len() => i as usize,
31 _ => return None,
32 };
33 let off = Self::IDX[i - 1] as usize;
34 Some(unsafe {
36 std::str::from_utf8_unchecked(std::slice::from_raw_parts(
37 Self::TAB.as_ptr().add(off),
38 Self::IDX[i] as usize - off,
39 ))
40 })
41 }
42}
43
44impl Debug for CompanyId {
45 #[inline]
46 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47 let name = self.name().unwrap_or("<unknown>");
48 f.debug_tuple("CompanyId")
49 .field(&format_args!("{:#06X} => \"{name}\"", self.0))
50 .finish()
51 }
52}
53
54impl Display for CompanyId {
55 #[inline]
56 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57 f.write_str(self.name().unwrap_or("<unknown>"))
58 }
59}
60
61impl From<CompanyId> for u16 {
62 #[inline(always)]
63 fn from(id: CompanyId) -> Self {
64 id.raw()
65 }
66}
67
68macro_rules! id_map {
71 {$first:literal => $name:literal, $($id:literal => $name_:literal,)+} => {
72 impl CompanyId {
73 const MIN: u16 = $first;
74 #[allow(clippy::no_effect)]
75 const MAX: u16 = { $($id);+ };
76 const FIRST: &'static str = $name;
77 #[allow(clippy::no_effect)]
78 #[cfg(test)]
79 const LAST: &'static str = { $($name_);+ };
80 const TAB: &'static [u8] = concat!($($name_),*).as_bytes();
81 const IDX: [u16; Self::MAX as usize - $first + 1] = {
82 let mut v = [0_u16; Self::MAX as usize - $first + 1];
83 let mut i = 0;
84 $(
85 i += 1;
86 assert!(i == $id - $first);
87 let (n, overflow) = v[i - 1].overflowing_add($name_.len() as u16);
88 assert!(!overflow);
89 v[i] = n;
90 )+
91 v
92 };
93 }
94 };
95}
96
97include!("company_id.rs");
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn company_ids() {
105 assert_eq!(CompanyId(CompanyId::MIN).name(), Some(CompanyId::FIRST));
106 assert_eq!(CompanyId(0x01F4).name(), Some("UTC Fire and Security"));
107 assert_eq!(CompanyId(CompanyId::MAX).name(), Some(CompanyId::LAST));
108 assert_eq!(CompanyId(CompanyId::MAX + 1).name(), None);
109 assert_eq!(CompanyId(u16::MAX).name(), None);
110 }
111}