font_types/
uint24.rs
1#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
5#[repr(transparent)]
6pub struct Uint24(u32);
7
8impl Uint24 {
9 pub const MIN: Self = Uint24(0);
11
12 pub const MAX: Self = Uint24(0xffffff);
14
15 pub const fn new(raw: u32) -> Uint24 {
17 let overflow = raw > Self::MAX.0;
18 let raw = raw * !overflow as u32 + Self::MAX.0 * overflow as u32;
19 Uint24(raw)
20 }
21
22 pub const fn checked_new(raw: u32) -> Option<Uint24> {
24 if raw > Self::MAX.0 {
25 None
26 } else {
27 Some(Uint24(raw))
28 }
29 }
30
31 pub const fn to_u32(self) -> u32 {
33 self.0
34 }
35
36 pub const fn to_be_bytes(self) -> [u8; 3] {
37 let bytes = self.0.to_be_bytes();
38 [bytes[1], bytes[2], bytes[3]]
39 }
40
41 pub const fn from_be_bytes(bytes: [u8; 3]) -> Self {
42 Uint24::new(((bytes[0] as u32) << 16) | ((bytes[1] as u32) << 8) | bytes[2] as u32)
43 }
44}
45
46impl From<Uint24> for u32 {
47 fn from(src: Uint24) -> u32 {
48 src.0
49 }
50}
51
52impl From<Uint24> for usize {
53 fn from(src: Uint24) -> usize {
54 src.0 as usize
55 }
56}
57
58#[derive(Debug)]
60pub struct TryFromUint24Error;
61
62impl std::fmt::Display for TryFromUint24Error {
63 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64 write!(f, "failed to convert usize value into Uint24.")
65 }
66}
67
68#[cfg(feature = "std")]
69impl std::error::Error for TryFromUint24Error {}
70
71impl TryFrom<usize> for Uint24 {
72 type Error = TryFromUint24Error;
73
74 fn try_from(value: usize) -> Result<Self, Self::Error> {
75 let u32_value = u32::try_from(value).map_err(|_| TryFromUint24Error)?;
76 Uint24::checked_new(u32_value).ok_or(TryFromUint24Error)
77 }
78}
79
80impl std::fmt::Display for Uint24 {
81 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
82 self.0.fmt(f)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn constructor() {
92 assert_eq!(Uint24::MAX, Uint24::new(u32::MAX));
93 assert!(Uint24::checked_new(u32::MAX).is_none())
94 }
95
96 #[test]
97 fn be_bytes() {
98 let bytes = [0xff, 0b10101010, 0b11001100];
99 let val = Uint24::from_be_bytes(bytes);
100 assert_eq!(val.to_be_bytes(), bytes);
101 }
102}