osom_primitives/
length.rs1#[repr(transparent)]
6#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
7#[must_use]
8pub struct Length {
9 size: u32,
10}
11
12#[repr(C)]
14#[derive(Debug, PartialEq, Eq, Clone, Copy)]
15pub enum LengthError {
16 Negative = 0,
18
19 OutOfMaxRange = 1,
21}
22
23impl Length {
24 pub const SAFE_MARGIN: u32 = 2048;
29
30 pub const MAX_LENGTH: Self = const {
33 const I32_MAX: u32 = i32::MAX as u32;
34 assert!(Self::SAFE_MARGIN >= 64, "SAFE_MARGIN has to be at least 64.");
35 assert!(
36 Self::SAFE_MARGIN < I32_MAX,
37 "SAFE_MARGIN has to be smaller than i32::MAX"
38 );
39 unsafe { Self::new_unchecked(I32_MAX - Self::SAFE_MARGIN) }
40 };
41
42 pub const ZERO: Self = unsafe { Self::new_unchecked(0) };
44
45 pub const ONE: Self = unsafe { Self::new_unchecked(1) };
47
48 #[inline(always)]
56 pub const unsafe fn new_unchecked(value: u32) -> Self {
57 Self { size: value }
58 }
59
60 #[inline(always)]
66 pub const fn try_from_u32(value: u32) -> Result<Self, LengthError> {
67 if value > Self::MAX_LENGTH.as_u32() {
68 Err(LengthError::OutOfMaxRange)
69 } else {
70 Ok(unsafe { Self::new_unchecked(value) })
71 }
72 }
73
74 #[inline(always)]
80 pub const fn try_from_i32(value: i32) -> Result<Self, LengthError> {
81 if value < 0 {
82 return Err(LengthError::Negative);
83 }
84
85 #[allow(clippy::cast_sign_loss)]
86 let value = value as u32;
87
88 Self::try_from_u32(value)
89 }
90
91 #[inline(always)]
93 #[must_use]
94 pub const fn as_u32(&self) -> u32 {
95 self.size
96 }
97
98 #[inline(always)]
100 #[must_use]
101 pub const fn as_usize(&self) -> usize {
102 self.size as usize
103 }
104}
105
106impl TryFrom<i32> for Length {
107 type Error = LengthError;
108
109 fn try_from(value: i32) -> Result<Self, Self::Error> {
110 Self::try_from_i32(value)
111 }
112}
113
114impl TryFrom<u32> for Length {
115 type Error = LengthError;
116
117 fn try_from(value: u32) -> Result<Self, Self::Error> {
118 Self::try_from_u32(value)
119 }
120}
121
122impl TryFrom<usize> for Length {
123 type Error = LengthError;
124
125 fn try_from(value: usize) -> Result<Self, Self::Error> {
126 if value > Length::MAX_LENGTH.as_usize() {
127 Err(LengthError::OutOfMaxRange)
128 } else {
129 #[allow(clippy::cast_possible_truncation)]
130 let value = value as u32;
131
132 Ok(unsafe { Self::new_unchecked(value) })
133 }
134 }
135}
136
137impl From<Length> for u32 {
138 fn from(value: Length) -> Self {
139 value.as_u32()
140 }
141}
142
143impl From<Length> for usize {
144 fn from(value: Length) -> Self {
145 value.as_usize()
146 }
147}
148
149impl core::fmt::Display for Length {
150 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
151 self.as_u32().fmt(f)
152 }
153}
154
155const _: () = const {
156 assert!(size_of::<Length>() == 4, "Length is expected to be of size 4");
157};