| // Copyright 2023 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /// Traits and utilities to handle length-type-value structures. |
| pub mod ltv; |
| |
| use crate::packet_encoding::{Encodable, Error as PacketError}; |
| |
| /// Represents the Advertising Set ID which is 1 byte long. |
| /// Follows little endian encoding. |
| #[derive(Debug, Clone, Copy, PartialEq)] |
| pub struct AdvertisingSetId(pub u8); |
| |
| impl AdvertisingSetId { |
| // Byte size if this is to be encoded. |
| pub const BYTE_SIZE: usize = 1; |
| } |
| |
| /// Represents the SyncInfo Interval value which is 2 bytes long. |
| /// Follows little endian encoding. |
| #[derive(Debug, Clone, Copy, PartialEq)] |
| pub struct PaInterval(pub u16); |
| |
| impl PaInterval { |
| pub const BYTE_SIZE: usize = 2; |
| pub const UNKNOWN_VALUE: u16 = 0xFFFF; |
| |
| pub const fn unknown() -> Self { |
| Self(Self::UNKNOWN_VALUE) |
| } |
| } |
| |
| impl Encodable for PaInterval { |
| type Error = PacketError; |
| |
| /// Encodees the PaInterval to 2 byte value using little endian encoding. |
| fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> { |
| if buf.len() < Self::BYTE_SIZE { |
| return Err(PacketError::BufferTooSmall); |
| } |
| buf[0..Self::BYTE_SIZE].copy_from_slice(&self.0.to_le_bytes()); |
| Ok(()) |
| } |
| |
| fn encoded_len(&self) -> core::primitive::usize { |
| Self::BYTE_SIZE |
| } |
| } |
| |
| /// Coding Format as defined by the Assigned Numbers Document. Section 2.11. |
| /// Referenced in the Core Spec 5.3, Volume 4, Part E, Section 7 as well as |
| /// various other profile specifications. |
| #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
| pub enum CodingFormat { |
| MuLawLog, |
| ALawLog, |
| Cvsd, |
| Transparent, |
| LinearPcm, |
| Msbc, |
| Lc3, |
| G729a, |
| VendorSpecific, |
| Unrecognized(u8), |
| } |
| |
| impl From<u8> for CodingFormat { |
| fn from(value: u8) -> Self { |
| match value { |
| 0x00 => Self::MuLawLog, |
| 0x01 => Self::ALawLog, |
| 0x02 => Self::Cvsd, |
| 0x03 => Self::Transparent, |
| 0x04 => Self::LinearPcm, |
| 0x05 => Self::Msbc, |
| 0x06 => Self::Lc3, |
| 0x07 => Self::G729a, |
| 0xFF => Self::VendorSpecific, |
| x => Self::Unrecognized(x), |
| } |
| } |
| } |
| |
| impl From<CodingFormat> for u8 { |
| fn from(value: CodingFormat) -> Self { |
| match value { |
| CodingFormat::MuLawLog => 0x00, |
| CodingFormat::ALawLog => 0x01, |
| CodingFormat::Cvsd => 0x02, |
| CodingFormat::Transparent => 0x03, |
| CodingFormat::LinearPcm => 0x04, |
| CodingFormat::Msbc => 0x05, |
| CodingFormat::Lc3 => 0x06, |
| CodingFormat::G729a => 0x07, |
| CodingFormat::VendorSpecific => 0xFF, |
| CodingFormat::Unrecognized(x) => x, |
| } |
| } |
| } |
| |
| impl core::fmt::Display for CodingFormat { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| match self { |
| CodingFormat::MuLawLog => write!(f, "ยต-law log"), |
| CodingFormat::ALawLog => write!(f, "A-law log"), |
| CodingFormat::Cvsd => write!(f, "CVSD"), |
| CodingFormat::Transparent => write!(f, "Transparent"), |
| CodingFormat::LinearPcm => write!(f, "Linear PCM"), |
| CodingFormat::Msbc => write!(f, "mSBC"), |
| CodingFormat::Lc3 => write!(f, "LC3"), |
| CodingFormat::G729a => write!(f, "G.729A"), |
| CodingFormat::VendorSpecific => write!(f, "Vendor Specific"), |
| CodingFormat::Unrecognized(x) => write!(f, "Unrecognized ({x})"), |
| } |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn encode_pa_interval() { |
| let mut buf = [0; PaInterval::BYTE_SIZE]; |
| let interval = PaInterval(0x1004); |
| |
| interval.encode(&mut buf[..]).expect("should succeed"); |
| assert_eq!(buf, [0x04, 0x10]); |
| } |
| |
| #[test] |
| fn encode_pa_interval_fails() { |
| let mut buf = [0; 1]; // Not enough buffer space. |
| let interval = PaInterval(0x1004); |
| |
| interval.encode(&mut buf[..]).expect_err("should fail"); |
| } |
| } |