blob: 749afdc138de5e7f859b62862d2bee2c040d0fe1 [file] [log] [blame]
//! custom types to be imported by hci packet pdl
//! (since hci depends on the packet library, we need to split these out)
use std::convert::TryFrom;
use std::fmt;
/// Signal for "empty" address
pub const EMPTY_ADDRESS: Address = Address { bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00] };
/// Signal for "any" address
pub const ANY_ADDRESS: Address = Address { bytes: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] };
/// A Bluetooth address
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub struct Address {
/// the actual bytes representing this address
pub bytes: [u8; 6],
}
impl Address {
/// whether this address is empty
pub fn is_empty(&self) -> bool {
*self == EMPTY_ADDRESS
}
}
impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
self.bytes[5],
self.bytes[4],
self.bytes[3],
self.bytes[2],
self.bytes[1],
self.bytes[0]
)
}
}
/// When you parse an address and it's not valid
#[derive(Debug, Clone)]
pub struct InvalidAddressError;
impl TryFrom<&[u8]> for Address {
type Error = InvalidAddressError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
if slice.len() == 6 {
match <[u8; 6]>::try_from(slice) {
Ok(bytes) => Ok(Self { bytes }),
Err(_) => Err(InvalidAddressError),
}
} else {
Err(InvalidAddressError)
}
}
}
impl From<Address> for [u8; 6] {
fn from(addr: Address) -> [u8; 6] {
addr.bytes
}
}
/// A Bluetooth class of device
#[derive(Clone, Eq, Copy, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub struct ClassOfDevice {
/// the actual bytes representing this class of device
pub bytes: [u8; 3],
}
impl fmt::Display for ClassOfDevice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:03X}-{:01X}-{:02X}",
((self.bytes[2] as u16) << 4) | ((self.bytes[1] as u16) >> 4),
self.bytes[1] & 0x0F,
self.bytes[0]
)
}
}
/// When you parse a class of device and it's not valid
#[derive(Debug, Clone)]
pub struct InvalidClassOfDeviceError;
impl TryFrom<&[u8]> for ClassOfDevice {
type Error = InvalidClassOfDeviceError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
if slice.len() == 3 {
match <[u8; 3]>::try_from(slice) {
Ok(bytes) => Ok(Self { bytes }),
Err(_) => Err(InvalidClassOfDeviceError),
}
} else {
Err(InvalidClassOfDeviceError)
}
}
}
impl From<ClassOfDevice> for [u8; 3] {
fn from(cod: ClassOfDevice) -> [u8; 3] {
cod.bytes
}
}