1#![no_std]
6
7#[derive(Debug)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub struct InvalidValue;
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19#[repr(u8)]
20pub enum Priority {
21 Exceptional = 0,
25 Immediate = 1,
29 Fast = 2,
33 High = 3,
42 Nominal = 4,
45 Low = 5,
49 Slow = 6,
53 Optional = 7,
58}
59
60impl Priority {
61 pub const MIN: Priority = Priority::Exceptional;
62 pub const MAX: Priority = Priority::Optional;
63
64 pub const fn try_from_u8(code: u8) -> Option<Priority> {
65 if code <= Self::MAX.into_u8() {
66 Some(Priority::from_u8_truncating(code))
67 } else {
68 None
69 }
70 }
71
72 pub const fn from_u8_truncating(code: u8) -> Priority {
73 match code & 0x7 {
74 0 => Priority::Exceptional,
75 1 => Priority::Immediate,
76 2 => Priority::Fast,
77 3 => Priority::High,
78 4 => Priority::Nominal,
79 5 => Priority::Low,
80 6 => Priority::Slow,
81 7 => Priority::Optional,
82 _ => unreachable!(),
83 }
84 }
85
86 pub const fn into_u8(self) -> u8 {
87 self as u8
88 }
89
90 pub const fn next(self) -> Option<Self> {
91 Self::try_from_u8(self.into_u8() + 1)
92 }
93
94 pub const fn prev(self) -> Option<Self> {
95 if let Some(code) = self.into_u8().checked_sub(1) {
96 Some(Self::from_u8_truncating(code))
97 } else {
98 None
99 }
100 }
101}
102
103impl From<Priority> for u8 {
104 fn from(value: Priority) -> Self {
105 value.into_u8()
106 }
107}
108
109impl From<Priority> for usize {
110 fn from(value: Priority) -> Self {
111 u8::from(value).into()
112 }
113}
114
115impl TryFrom<u8> for Priority {
116 type Error = InvalidValue;
117
118 fn try_from(value: u8) -> Result<Self, Self::Error> {
119 Self::try_from_u8(value).ok_or(InvalidValue)
120 }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130pub struct PrioritySet(u8);
131
132impl PrioritySet {
133 pub const NONE: Self = Self(0);
134 pub const ALL: Self = Self(u8::MAX);
135
136 pub const fn from_bits(bits: u8) -> Self {
137 Self(bits)
138 }
139
140 pub const fn into_bits(self) -> u8 {
141 self.0
142 }
143
144 pub const fn complement(self) -> Self {
145 Self(!self.0)
146 }
147
148 pub const fn new_eq(priority: Priority) -> Self {
149 Self(1u8 << priority.into_u8())
150 }
151
152 pub const fn new_ge(priority: Priority) -> Self {
153 Self(u8::MAX << priority.into_u8())
154 }
155
156 pub const fn new_le(priority: Priority) -> Self {
157 Self(u8::MAX >> (Priority::MAX.into_u8() - priority.into_u8()))
158 }
159
160 pub const fn new_gt(priority: Priority) -> Self {
161 Self::new_le(priority).complement()
162 }
163
164 pub const fn new_lt(priority: Priority) -> Self {
165 Self::new_ge(priority).complement()
166 }
167
168 pub const fn contains(&self, priority: Priority) -> bool {
169 (self.0 >> priority.into_u8()) & 0x1 != 0
170 }
171
172 pub const fn insert(&mut self, priority: Priority) {
173 self.0 |= Self::new_eq(priority).0
174 }
175
176 pub const fn remove(&mut self, priority: Priority) {
177 self.0 &= Self::new_eq(priority).complement().0
178 }
179
180 pub const fn first(&self) -> Option<Priority> {
181 Priority::try_from_u8(self.0.trailing_zeros() as u8)
182 }
183
184 pub const fn last(&self) -> Option<Priority> {
185 let n = u8::BITS - self.0.leading_zeros();
186 Priority::try_from_u8((n as u8).wrapping_sub(1))
187 }
188
189 pub const fn is_empty(&self) -> bool {
190 self.0 == Self::NONE.0
191 }
192}
193
194impl Default for PrioritySet {
195 fn default() -> Self {
196 PrioritySet::NONE
197 }
198}
199
200impl core::ops::Not for PrioritySet {
201 type Output = Self;
202 fn not(self) -> Self::Output {
203 Self(!self.0)
204 }
205}
206
207impl core::ops::BitAnd<PrioritySet> for PrioritySet {
208 type Output = Self;
209 fn bitand(self, rhs: PrioritySet) -> Self::Output {
210 PrioritySet(self.0 & rhs.0)
211 }
212}
213
214impl core::ops::BitAndAssign<PrioritySet> for PrioritySet {
215 fn bitand_assign(&mut self, rhs: PrioritySet) {
216 self.0 &= rhs.0
217 }
218}
219
220impl core::ops::BitOr<PrioritySet> for PrioritySet {
221 type Output = Self;
222 fn bitor(self, rhs: PrioritySet) -> Self::Output {
223 PrioritySet(self.0 | rhs.0)
224 }
225}
226
227impl core::ops::BitOrAssign<PrioritySet> for PrioritySet {
228 fn bitor_assign(&mut self, rhs: PrioritySet) {
229 self.0 |= rhs.0;
230 }
231}
232
233impl core::iter::IntoIterator for PrioritySet {
234 type Item = Priority;
235 type IntoIter = PrioritySetIterator;
236 fn into_iter(self) -> Self::IntoIter {
237 PrioritySetIterator { residual: self }
238 }
239}
240
241pub struct PrioritySetIterator {
242 residual: PrioritySet,
243}
244
245impl core::iter::Iterator for PrioritySetIterator {
246 type Item = Priority;
247 fn next(&mut self) -> Option<Self::Item> {
248 let first = self.residual.first();
249 if let Some(priority) = first {
250 self.residual.remove(priority);
251 }
252 first
253 }
254}
255
256#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
258pub struct NodeId(u8);
259
260impl NodeId {
261 const MAX_VALUE: u8 = 0x7f;
262 pub const MAX: NodeId = NodeId(0x7f);
263
264 pub const fn new(value: u8) -> Option<Self> {
265 if value <= Self::MAX_VALUE {
266 Some(Self::from_u8_truncating(value))
267 } else {
268 None
269 }
270 }
271
272 pub const fn from_u8_truncating(value: u8) -> Self {
273 Self(value & Self::MAX_VALUE)
274 }
275
276 pub const fn into_u8(self) -> u8 {
277 self.0
278 }
279}
280
281impl From<NodeId> for u8 {
282 fn from(value: NodeId) -> Self {
283 value.into_u8()
284 }
285}
286
287impl From<NodeId> for usize {
288 fn from(value: NodeId) -> Self {
289 u8::from(value).into()
290 }
291}
292
293impl TryFrom<u8> for NodeId {
294 type Error = InvalidValue;
295
296 fn try_from(value: u8) -> Result<Self, Self::Error> {
297 Self::new(value).ok_or(InvalidValue)
298 }
299}
300
301#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
302#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303pub struct SubjectId(u16);
304
305impl SubjectId {
306 const MAX_VALUE: u16 = 0x1fff;
307 pub const MAX: SubjectId = SubjectId(Self::MAX_VALUE);
308
309 pub const fn new(value: u16) -> Option<Self> {
310 if value <= Self::MAX_VALUE {
311 Some(Self::from_u16_truncating(value))
312 } else {
313 None
314 }
315 }
316
317 pub const fn from_u16_truncating(value: u16) -> Self {
318 Self(value & Self::MAX_VALUE)
319 }
320
321 pub const fn into_u16(self) -> u16 {
322 self.0
323 }
324}
325
326impl From<SubjectId> for u16 {
327 fn from(value: SubjectId) -> Self {
328 value.into_u16()
329 }
330}
331
332impl TryFrom<u16> for SubjectId {
333 type Error = InvalidValue;
334
335 fn try_from(value: u16) -> Result<Self, Self::Error> {
336 Self::new(value).ok_or(InvalidValue)
337 }
338}
339
340#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
341#[cfg_attr(feature = "defmt", derive(defmt::Format))]
342pub struct ServiceId(u16);
343
344impl ServiceId {
345 const MAX_VALUE: u16 = 0x1ff;
346 pub const MAX: SubjectId = SubjectId(Self::MAX_VALUE);
347
348 pub const fn new(value: u16) -> Option<Self> {
349 if value <= Self::MAX_VALUE {
350 Some(Self::from_u16_truncating(value))
351 } else {
352 None
353 }
354 }
355
356 pub const fn from_u16_truncating(value: u16) -> Self {
357 Self(value & Self::MAX_VALUE)
358 }
359
360 pub const fn into_u16(self) -> u16 {
361 self.0
362 }
363}
364
365impl From<ServiceId> for u16 {
366 fn from(value: ServiceId) -> Self {
367 value.into_u16()
368 }
369}
370
371impl TryFrom<u16> for ServiceId {
372 type Error = InvalidValue;
373
374 fn try_from(value: u16) -> Result<Self, Self::Error> {
375 Self::new(value).ok_or(InvalidValue)
376 }
377}
378
379#[derive(Debug, Copy, Clone, PartialEq, Eq)]
380#[cfg_attr(feature = "defmt", derive(defmt::Format))]
381pub struct TransferId(u8);
382
383impl TransferId {
384 const MAX_VALUE: u8 = 0x1f;
385 pub const MAX: TransferId = TransferId(Self::MAX_VALUE);
386
387 pub const SESSION_START: TransferId = TransferId(0);
389
390 pub const fn new(value: u8) -> Option<Self> {
391 if value <= Self::MAX_VALUE {
392 Some(Self::from_u8_truncating(value))
393 } else {
394 None
395 }
396 }
397
398 pub const fn from_u8_truncating(value: u8) -> Self {
399 Self(value & Self::MAX_VALUE)
400 }
401
402 pub const fn into_u8(self) -> u8 {
403 self.0
404 }
405
406 pub fn next(self) -> Self {
407 Self((self.0 + 1) & Self::MAX.0)
408 }
409}
410
411impl Default for TransferId {
412 fn default() -> Self {
413 Self::SESSION_START
414 }
415}
416
417impl From<TransferId> for u8 {
418 fn from(value: TransferId) -> Self {
419 value.into_u8()
420 }
421}
422
423impl TryFrom<u8> for TransferId {
424 type Error = InvalidValue;
425
426 fn try_from(value: u8) -> Result<Self, Self::Error> {
427 Self::new(value).ok_or(InvalidValue)
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 #[test]
436 fn test_priority_set() {
437 let mut set = PrioritySet::NONE;
438 set.insert(Priority::Fast);
439 set.insert(Priority::Nominal);
440
441 assert_eq!(set.first(), Some(Priority::Fast));
442 assert_eq!(set.last(), Some(Priority::Nominal));
443 }
444
445 #[test]
446 fn test_priority_set_ge() {
447 let set = PrioritySet::new_ge(Priority::Optional);
448 assert!(!set.contains(Priority::Slow));
449 assert!(set.contains(Priority::Optional));
450
451 let set = PrioritySet::new_ge(Priority::Exceptional);
452 assert_eq!(set, PrioritySet::ALL);
453 }
454
455 #[test]
456 fn test_priority_set_le() {
457 let set = PrioritySet::new_le(Priority::Optional);
458 assert_eq!(set, PrioritySet::ALL);
459
460 let set = PrioritySet::new_le(Priority::Exceptional);
461 assert!(set.contains(Priority::Exceptional));
462 assert!(!set.contains(Priority::Immediate));
463 }
464
465 #[test]
466 fn test_priority_set_gt() {
467 let set = PrioritySet::new_gt(Priority::Optional);
468 assert_eq!(set, PrioritySet::NONE);
469
470 let set = PrioritySet::new_gt(Priority::Exceptional);
471 assert!(!set.contains(Priority::Exceptional));
472 assert!(set.contains(Priority::Immediate));
473 }
474
475 #[test]
476 fn test_priority_set_lt() {
477 let set = PrioritySet::new_lt(Priority::Optional);
478 assert!(set.contains(Priority::Slow));
479 assert!(!set.contains(Priority::Optional));
480
481 let set = PrioritySet::new_lt(Priority::Exceptional);
482 assert_eq!(set, PrioritySet::NONE);
483 }
484}