usbd_midi/message/data/
u4.rs

1//! A primitive value with 4-bit length.
2
3use crate::message::data::{FromClamped, FromOverFlow};
4
5/// A primitive value that can be from 0-0x0F
6#[derive(Debug, Clone, Eq, PartialEq)]
7pub struct U4(u8);
8
9/// Error representing that this value is not a valid u4
10#[derive(Debug, Clone, Eq, PartialEq)]
11pub struct InvalidU4(pub u8);
12
13impl TryFrom<u8> for U4 {
14    type Error = InvalidU4;
15
16    fn try_from(value: u8) -> Result<Self, Self::Error> {
17        if value > U4::MAX.0 {
18            Err(InvalidU4(value))
19        } else {
20            Ok(U4(value))
21        }
22    }
23}
24
25impl From<U4> for u8 {
26    fn from(value: U4) -> u8 {
27        value.0
28    }
29}
30
31impl FromOverFlow<u8> for U4 {
32    fn from_overflow(value: u8) -> U4 {
33        const MASK: u8 = 0b0000_1111;
34        let value = MASK & value;
35        U4(value)
36    }
37}
38
39impl FromClamped<u8> for U4 {
40    fn from_clamped(value: u8) -> U4 {
41        match U4::try_from(value) {
42            Ok(x) => x,
43            _ => U4::MAX,
44        }
45    }
46}
47
48impl U4 {
49    /// Maximum value for the type.
50    pub const MAX: U4 = U4(0x0F);
51    /// Minimum value for the type.
52    pub const MIN: U4 = U4(0);
53
54    /// Combines two nibbles (u4) eg half byte
55    /// result will be a full byte
56    pub fn combine(upper: U4, lower: U4) -> u8 {
57        let upper = upper.0.overflowing_shl(8).0;
58        let lower = lower.0 & U4::MAX.0;
59        upper | lower
60    }
61
62    /// Constructs a U4 from a u8.
63    /// Note this clamps off the upper portions
64    pub fn from_overflowing_u8(value: u8) -> U4 {
65        const MASK: u8 = 0b0000_1111;
66        let number = MASK & value;
67        U4(number)
68    }
69}