blob: 0fa24dace703fa31cea4b244bece5ced9b479cd3 [file] [log] [blame]
// Copyright 2023 Google LLC
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// A Uuid as defined by the Core Specification (v5.4, Vol 3, Part B, Sec 2.5.1)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Uuid(uuid::Uuid);
impl Uuid {
// Non-changing parts of the Bluetooth Base UUID, for easy comparison and construction.
const BASE_UUID_B_PART: u16 = 0x0000;
const BASE_UUID_C_PART: u16 = 0x1000;
const BASE_UUID_D_PART: [u8; 8] = [0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB];
pub const fn from_u16(value: u16) -> Self {
Self::from_u32(value as u32)
}
pub const fn from_u32(value: u32) -> Self {
Uuid(uuid::Uuid::from_fields(
value,
Self::BASE_UUID_B_PART,
Self::BASE_UUID_C_PART,
&Self::BASE_UUID_D_PART,
))
}
pub fn to_u16(&self) -> Option<u16> {
let x: u32 = self.to_u32()?;
x.try_into().ok()
}
pub fn to_u32(&self) -> Option<u32> {
let (first, second, third, final_bytes) = self.0.as_fields();
if second != Uuid::BASE_UUID_B_PART
|| third != Uuid::BASE_UUID_C_PART
|| final_bytes != &Uuid::BASE_UUID_D_PART
{
return None;
}
Some(first)
}
}
impl From<Uuid> for uuid::Uuid {
fn from(value: Uuid) -> Self {
value.0
}
}
impl From<uuid::Uuid> for Uuid {
fn from(value: uuid::Uuid) -> Self {
Uuid(value)
}
}
impl core::fmt::Display for Uuid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.as_hyphenated())
}
}
impl core::str::FromStr for Uuid {
type Err = uuid::Error;
fn from_str(s: &str) -> core::result::Result<Uuid, Self::Err> {
uuid::Uuid::parse_str(s).map(|uuid| Uuid(uuid))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn uuid16() {
let uuid = Uuid::from_u16(0x180d);
assert_eq!("0000180d-0000-1000-8000-00805f9b34fb", uuid.to_string());
let as16: u16 = uuid.to_u16().unwrap();
assert_eq!(0x180d, as16);
}
}