1pub mod ltv;
7
8use crate::packet_encoding::{Encodable, Error as PacketError};
9use std::str::FromStr;
10
11pub type Address = [u8; 6];
15
16#[repr(u8)]
18#[derive(Clone, Copy, Debug, PartialEq)]
19pub enum AddressType {
20 Public = 0x00,
21 Random = 0x01,
22}
23
24impl AddressType {
25 pub const BYTE_SIZE: usize = 1;
26}
27
28impl TryFrom<u8> for AddressType {
29 type Error = PacketError;
30
31 fn try_from(value: u8) -> Result<Self, Self::Error> {
32 match value {
33 0x00 => Ok(Self::Public),
34 0x01 => Ok(Self::Random),
35 _ => Err(PacketError::OutOfRange),
36 }
37 }
38}
39
40impl FromStr for AddressType {
41 type Err = PacketError;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 match s {
45 "Public" => Ok(AddressType::Public),
46 "Random" => Ok(AddressType::Random),
47 _ => Err(PacketError::InvalidParameter(format!("invalid address type: {s}"))),
48 }
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq)]
54pub struct AdvertisingSetId(pub u8);
55
56impl AdvertisingSetId {
57 pub const BYTE_SIZE: usize = 1;
59}
60
61#[derive(Debug, Clone, Copy, PartialEq)]
63pub struct PaInterval(pub u16);
64
65impl PaInterval {
66 pub const BYTE_SIZE: usize = 2;
67 pub const UNKNOWN_VALUE: u16 = 0xFFFF;
68
69 pub const fn unknown() -> Self {
70 Self(Self::UNKNOWN_VALUE)
71 }
72}
73
74impl Encodable for PaInterval {
75 type Error = PacketError;
76
77 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
79 if buf.len() < Self::BYTE_SIZE {
80 return Err(PacketError::BufferTooSmall);
81 }
82 buf[0..Self::BYTE_SIZE].copy_from_slice(&self.0.to_le_bytes());
83 Ok(())
84 }
85
86 fn encoded_len(&self) -> core::primitive::usize {
87 Self::BYTE_SIZE
88 }
89}
90
91#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
95pub enum CodingFormat {
96 MuLawLog,
97 ALawLog,
98 Cvsd,
99 Transparent,
100 LinearPcm,
101 Msbc,
102 Lc3,
103 G729a,
104 VendorSpecific,
105 Unrecognized(u8),
106}
107
108impl From<u8> for CodingFormat {
109 fn from(value: u8) -> Self {
110 match value {
111 0x00 => Self::MuLawLog,
112 0x01 => Self::ALawLog,
113 0x02 => Self::Cvsd,
114 0x03 => Self::Transparent,
115 0x04 => Self::LinearPcm,
116 0x05 => Self::Msbc,
117 0x06 => Self::Lc3,
118 0x07 => Self::G729a,
119 0xFF => Self::VendorSpecific,
120 x => Self::Unrecognized(x),
121 }
122 }
123}
124
125impl From<CodingFormat> for u8 {
126 fn from(value: CodingFormat) -> Self {
127 match value {
128 CodingFormat::MuLawLog => 0x00,
129 CodingFormat::ALawLog => 0x01,
130 CodingFormat::Cvsd => 0x02,
131 CodingFormat::Transparent => 0x03,
132 CodingFormat::LinearPcm => 0x04,
133 CodingFormat::Msbc => 0x05,
134 CodingFormat::Lc3 => 0x06,
135 CodingFormat::G729a => 0x07,
136 CodingFormat::VendorSpecific => 0xFF,
137 CodingFormat::Unrecognized(x) => x,
138 }
139 }
140}
141
142impl core::fmt::Display for CodingFormat {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 match self {
145 CodingFormat::MuLawLog => write!(f, "ยต-law log"),
146 CodingFormat::ALawLog => write!(f, "A-law log"),
147 CodingFormat::Cvsd => write!(f, "CVSD"),
148 CodingFormat::Transparent => write!(f, "Transparent"),
149 CodingFormat::LinearPcm => write!(f, "Linear PCM"),
150 CodingFormat::Msbc => write!(f, "mSBC"),
151 CodingFormat::Lc3 => write!(f, "LC3"),
152 CodingFormat::G729a => write!(f, "G.729A"),
153 CodingFormat::VendorSpecific => write!(f, "Vendor Specific"),
154 CodingFormat::Unrecognized(x) => write!(f, "Unrecognized ({x})"),
155 }
156 }
157}
158
159#[derive(Debug, Clone, PartialEq)]
161pub enum CodecId {
162 Assigned(CodingFormat),
165 VendorSpecific {
166 company_id: crate::CompanyId,
167 vendor_specific_codec_id: u16,
168 },
169}
170
171impl CodecId {
172 pub const BYTE_SIZE: usize = 5;
173}
174
175impl crate::packet_encoding::Decodable for CodecId {
176 type Error = crate::packet_encoding::Error;
177
178 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
179 if buf.len() < 5 {
180 return (Err(crate::packet_encoding::Error::UnexpectedDataLength), buf.len());
181 }
182 let format = buf[0].into();
183 if format != CodingFormat::VendorSpecific {
184 return (Ok(Self::Assigned(format)), 5);
186 }
187 let company_id = u16::from_le_bytes([buf[1], buf[2]]).into();
188 let vendor_specific_codec_id = u16::from_le_bytes([buf[3], buf[4]]);
189 (Ok(Self::VendorSpecific { company_id, vendor_specific_codec_id }), 5)
190 }
191}
192
193impl Encodable for CodecId {
194 type Error = PacketError;
195
196 fn encoded_len(&self) -> core::primitive::usize {
197 Self::BYTE_SIZE
198 }
199
200 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
201 if buf.len() < Self::BYTE_SIZE {
202 return Err(Self::Error::BufferTooSmall);
203 }
204 match self {
205 CodecId::Assigned(format) => {
206 buf[0] = (*format).into();
207 buf[1..5].fill(0);
208 }
209 CodecId::VendorSpecific { company_id, vendor_specific_codec_id } => {
210 buf[0] = 0xFF;
211 [buf[1], buf[2]] = u16::from(*company_id).to_le_bytes();
212 [buf[3], buf[4]] = vendor_specific_codec_id.to_le_bytes();
213 }
214 }
215 Ok(())
216 }
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
220pub enum Phy {
221 Le1m,
223 Le2m,
225 LeCoded,
227}
228
229#[cfg(test)]
230mod tests {
231 use crate::packet_encoding::Decodable;
232
233 use super::*;
234 use std::str::FromStr;
235
236 #[test]
237 fn address_type_from_str() {
238 let addr_type = AddressType::from_str("Public").expect("should succeed");
239 assert_eq!(addr_type, AddressType::Public);
240 let addr_type = AddressType::from_str("Random").expect("should succeed");
241 assert_eq!(addr_type, AddressType::Random);
242 AddressType::from_str("invalid").expect_err("should fail");
243 }
244
245 #[test]
246 fn encode_pa_interval() {
247 let mut buf = [0; PaInterval::BYTE_SIZE];
248 let interval = PaInterval(0x1004);
249
250 interval.encode(&mut buf[..]).expect("should succeed");
251 assert_eq!(buf, [0x04, 0x10]);
252 }
253
254 #[test]
255 fn encode_pa_interval_fails() {
256 let mut buf = [0; 1]; let interval = PaInterval(0x1004);
258
259 interval.encode(&mut buf[..]).expect_err("should fail");
260 }
261
262 #[test]
263 fn decode_codec_id() {
264 let assigned = [0x01, 0x00, 0x00, 0x00, 0x00];
265 let (codec_id, _) = CodecId::decode(&assigned[..]);
266 assert_eq!(codec_id, Ok(CodecId::Assigned(CodingFormat::ALawLog)));
267
268 let vendor_specific = [0xFF, 0x36, 0xFD, 0x11, 0x22];
269 let (codec_id, _) = CodecId::decode(&vendor_specific[..]);
270 assert_eq!(
271 codec_id,
272 Ok(CodecId::VendorSpecific {
273 company_id: (0xFD36 as u16).into(),
274 vendor_specific_codec_id: 0x2211
275 })
276 );
277 }
278
279 #[test]
280 fn encode_codec_id() {
281 let assigned = [0x01, 0x00, 0x00, 0x00, 0x00];
282 let (codec_id, _) = CodecId::decode(&assigned[..]);
283 assert_eq!(codec_id, Ok(CodecId::Assigned(CodingFormat::ALawLog)));
284
285 let vendor_specific = [0xFF, 0x36, 0xFD, 0x11, 0x22];
286 let (codec_id, _) = CodecId::decode(&vendor_specific[..]);
287 assert_eq!(
288 codec_id,
289 Ok(CodecId::VendorSpecific {
290 company_id: (0xFD36 as u16).into(),
291 vendor_specific_codec_id: 0x2211
292 })
293 );
294 }
295}