trouble_host/types/
uuid.rs

1//! UUID types.
2
3use bt_hci::uuid::BluetoothUuid16;
4
5use crate::codec::{Decode, Encode, Error, Type};
6
7/// A 16-bit or 128-bit UUID.
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9#[derive(Debug, PartialEq, Clone)]
10pub enum Uuid {
11    /// 16-bit UUID
12    Uuid16([u8; 2]),
13    /// 128-bit UUID
14    Uuid128([u8; 16]),
15}
16
17impl From<BluetoothUuid16> for Uuid {
18    fn from(data: bt_hci::uuid::BluetoothUuid16) -> Self {
19        Uuid::Uuid16(data.into())
20    }
21}
22
23impl From<u128> for Uuid {
24    fn from(data: u128) -> Self {
25        Uuid::Uuid128(data.to_le_bytes())
26    }
27}
28
29impl From<[u8; 16]> for Uuid {
30    fn from(data: [u8; 16]) -> Self {
31        Uuid::Uuid128(data)
32    }
33}
34
35impl From<[u8; 2]> for Uuid {
36    fn from(data: [u8; 2]) -> Self {
37        Uuid::Uuid16(data)
38    }
39}
40
41impl From<u16> for Uuid {
42    fn from(data: u16) -> Self {
43        Uuid::Uuid16(data.to_le_bytes())
44    }
45}
46
47impl Uuid {
48    /// Create a new 16-bit UUID.
49    pub const fn new_short(val: u16) -> Self {
50        Self::Uuid16(val.to_le_bytes())
51    }
52
53    /// Create a new 128-bit UUID.
54    pub const fn new_long(val: [u8; 16]) -> Self {
55        Self::Uuid128(val)
56    }
57
58    /// Copy the UUID bytes into a slice.
59    pub fn bytes(&self, data: &mut [u8]) {
60        match self {
61            Uuid::Uuid16(uuid) => data.copy_from_slice(uuid),
62            Uuid::Uuid128(uuid) => data.copy_from_slice(uuid),
63        }
64    }
65
66    /// Get the UUID type.
67    pub fn get_type(&self) -> u8 {
68        match self {
69            Uuid::Uuid16(_) => 0x01,
70            Uuid::Uuid128(_) => 0x02,
71        }
72    }
73
74    pub(crate) fn size(&self) -> usize {
75        match self {
76            Uuid::Uuid16(_) => 6,
77            Uuid::Uuid128(_) => 20,
78        }
79    }
80
81    /// Get the 16-bit UUID value.
82    pub fn as_short(&self) -> u16 {
83        match self {
84            Uuid::Uuid16(data) => u16::from_le_bytes([data[0], data[1]]),
85            _ => panic!("wrong type"),
86        }
87    }
88
89    /// Get the 128-bit UUID value.
90    pub fn as_raw(&self) -> &[u8] {
91        match self {
92            Uuid::Uuid16(uuid) => uuid,
93            Uuid::Uuid128(uuid) => uuid,
94        }
95    }
96}
97
98impl TryFrom<&[u8]> for Uuid {
99    type Error = crate::Error;
100
101    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
102        match value.len() {
103            // Slice length has already been verified, so unwrap can be used
104            2 => Ok(Uuid::Uuid16(value.try_into().unwrap())),
105            16 => {
106                let mut bytes = [0; 16];
107                bytes.copy_from_slice(value);
108                Ok(Uuid::Uuid128(bytes))
109            }
110            _ => Err(crate::Error::InvalidUuidLength(value.len())),
111        }
112    }
113}
114
115impl Type for Uuid {
116    fn size(&self) -> usize {
117        self.as_raw().len()
118    }
119}
120
121impl Decode<'_> for Uuid {
122    fn decode(src: &[u8]) -> Result<Self, Error> {
123        if src.len() < 2 {
124            Err(Error::InvalidValue)
125        } else {
126            let val: u16 = u16::from_le_bytes([src[0], src[1]]);
127            // Must be a long id
128            if val == 0 {
129                if src.len() < 16 {
130                    return Err(Error::InvalidValue);
131                }
132                Ok(Uuid::Uuid128(src[0..16].try_into().map_err(|_| Error::InvalidValue)?))
133            } else {
134                Ok(Uuid::new_short(val))
135            }
136        }
137    }
138}
139
140impl Encode for Uuid {
141    fn encode(&self, dest: &mut [u8]) -> Result<(), Error> {
142        self.bytes(dest);
143        Ok(())
144    }
145}