use bt_hci::uuid::{BluetoothUuid128, BluetoothUuid16};
use crate::codec::{Decode, Encode, Error, Type};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Uuid {
Uuid16([u8; 2]),
Uuid128([u8; 16]),
}
impl From<BluetoothUuid16> for Uuid {
fn from(data: bt_hci::uuid::BluetoothUuid16) -> Self {
Uuid::Uuid16(data.into())
}
}
impl From<BluetoothUuid128> for Uuid {
fn from(data: bt_hci::uuid::BluetoothUuid128) -> Self {
Uuid::Uuid128(data.into())
}
}
impl From<u128> for Uuid {
fn from(data: u128) -> Self {
Uuid::Uuid128(data.to_le_bytes())
}
}
impl From<[u8; 16]> for Uuid {
fn from(data: [u8; 16]) -> Self {
Uuid::Uuid128(data)
}
}
impl From<[u8; 2]> for Uuid {
fn from(data: [u8; 2]) -> Self {
Uuid::Uuid16(data)
}
}
impl From<u16> for Uuid {
fn from(data: u16) -> Self {
Uuid::Uuid16(data.to_le_bytes())
}
}
impl Uuid {
pub const fn new_short(val: u16) -> Self {
Self::Uuid16(val.to_le_bytes())
}
pub const fn new_long(val: [u8; 16]) -> Self {
Self::Uuid128(val)
}
pub fn bytes(&self, data: &mut [u8]) {
match self {
Uuid::Uuid16(uuid) => data.copy_from_slice(uuid),
Uuid::Uuid128(uuid) => data.copy_from_slice(uuid),
}
}
pub fn get_type(&self) -> u8 {
match self {
Uuid::Uuid16(_) => 0x01,
Uuid::Uuid128(_) => 0x02,
}
}
pub(crate) fn size(&self) -> usize {
match self {
Uuid::Uuid16(_) => 6,
Uuid::Uuid128(_) => 20,
}
}
pub fn as_short(&self) -> u16 {
match self {
Uuid::Uuid16(data) => u16::from_le_bytes([data[0], data[1]]),
_ => panic!("wrong type"),
}
}
pub fn as_raw(&self) -> &[u8] {
match self {
Uuid::Uuid16(uuid) => uuid,
Uuid::Uuid128(uuid) => uuid,
}
}
}
impl TryFrom<&[u8]> for Uuid {
type Error = crate::Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
match value.len() {
2 => Ok(Uuid::Uuid16(value.try_into().unwrap())),
16 => {
let mut bytes = [0; 16];
bytes.copy_from_slice(value);
Ok(Uuid::Uuid128(bytes))
}
_ => Err(crate::Error::InvalidUuidLength(value.len())),
}
}
}
impl Type for Uuid {
fn size(&self) -> usize {
self.as_raw().len()
}
}
impl Decode<'_> for Uuid {
fn decode(src: &[u8]) -> Result<Self, Error> {
if src.len() < 2 {
Err(Error::InvalidValue)
} else {
let val: u16 = u16::from_le_bytes([src[0], src[1]]);
if val == 0 {
if src.len() < 16 {
return Err(Error::InvalidValue);
}
Ok(Uuid::Uuid128(src[0..16].try_into().map_err(|_| Error::InvalidValue)?))
} else {
Ok(Uuid::new_short(val))
}
}
}
}
impl Encode for Uuid {
fn encode(&self, dest: &mut [u8]) -> Result<(), Error> {
self.bytes(dest);
Ok(())
}
}