1use bt_bap::types::BroadcastId;
6use bt_common::core::ltv::LtValue;
7use bt_common::core::{AddressType, AdvertisingSetId, PeriodicAdvertisingInterval};
8use bt_common::generic_audio::metadata_ltv::*;
9use bt_common::packet_encoding::{Decodable, Encodable, Error as PacketError};
10use bt_common::{decodable_enum, Uuid};
11use std::str::FromStr;
12
13pub const ADDRESS_BYTE_SIZE: usize = 6;
14const NUM_SUBGROUPS_BYTE_SIZE: usize = 1;
15const PA_SYNC_BYTE_SIZE: usize = 1;
16const SOURCE_ID_BYTE_SIZE: usize = 1;
17
18pub const BROADCAST_AUDIO_SCAN_SERVICE_UUID: Uuid = Uuid::from_u16(0x184F);
21pub const BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID: Uuid = Uuid::from_u16(0x2BC7);
22pub const BROADCAST_RECEIVE_STATE_UUID: Uuid = Uuid::from_u16(0x2BC8);
23
24pub type SourceId = u8;
25
26pub type SubgroupIndex = u8;
29
30pub type BisIndex = u8;
32
33decodable_enum! {
34 pub enum ControlPointOpcode<u8, bt_common::packet_encoding::Error, OutOfRange> {
35 RemoteScanStopped = 0x00,
36 RemoteScanStarted = 0x01,
37 AddSource = 0x02,
38 ModifySource = 0x03,
39 SetBroadcastCode = 0x04,
40 RemoveSource = 0x05,
41 }
42}
43
44impl ControlPointOpcode {
47 const BYTE_SIZE: usize = 1;
48}
49
50pub trait ControlPointOperation: Encodable<Error = PacketError> {
57 fn opcode() -> ControlPointOpcode;
59
60 fn check_opcode(raw_value: u8) -> Result<ControlPointOpcode, PacketError> {
63 let expected = Self::opcode();
64 let got = ControlPointOpcode::try_from(raw_value)?;
65 if got != expected {
66 return Err(PacketError::InvalidParameter(format!(
67 "got opcode {got:?}, expected {expected:?}"
68 )));
69 }
70 Ok(got)
71 }
72}
73
74#[derive(Debug, PartialEq)]
76pub struct RemoteScanStoppedOperation;
77
78impl ControlPointOperation for RemoteScanStoppedOperation {
79 fn opcode() -> ControlPointOpcode {
80 ControlPointOpcode::RemoteScanStopped
81 }
82}
83
84impl Decodable for RemoteScanStoppedOperation {
85 type Error = PacketError;
86
87 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
88 const BYTE_SIZE: usize = ControlPointOpcode::BYTE_SIZE;
89 if buf.len() < BYTE_SIZE {
90 return (Err(PacketError::UnexpectedDataLength), buf.len());
91 }
92 (Self::check_opcode(buf[0]).map(|_| RemoteScanStoppedOperation), BYTE_SIZE)
93 }
94}
95
96impl Encodable for RemoteScanStoppedOperation {
97 type Error = PacketError;
98
99 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
100 if buf.len() < self.encoded_len() {
101 return Err(PacketError::BufferTooSmall);
102 }
103 buf[0] = Self::opcode() as u8;
104 Ok(())
105 }
106
107 fn encoded_len(&self) -> core::primitive::usize {
108 ControlPointOpcode::BYTE_SIZE
109 }
110}
111
112#[derive(Debug, PartialEq)]
114pub struct RemoteScanStartedOperation;
115
116impl ControlPointOperation for RemoteScanStartedOperation {
117 fn opcode() -> ControlPointOpcode {
118 ControlPointOpcode::RemoteScanStarted
119 }
120}
121
122impl Decodable for RemoteScanStartedOperation {
123 type Error = PacketError;
124
125 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
126 const BYTE_SIZE: usize = ControlPointOpcode::BYTE_SIZE;
127 if buf.len() < BYTE_SIZE {
128 return (Err(PacketError::UnexpectedDataLength), buf.len());
129 }
130 (Self::check_opcode(buf[0]).map(|_| RemoteScanStartedOperation), BYTE_SIZE)
131 }
132}
133
134impl Encodable for RemoteScanStartedOperation {
135 type Error = PacketError;
136
137 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
138 if buf.len() < self.encoded_len() {
139 return Err(PacketError::BufferTooSmall);
140 }
141 buf[0] = Self::opcode() as u8;
142 Ok(())
143 }
144
145 fn encoded_len(&self) -> core::primitive::usize {
146 ControlPointOpcode::BYTE_SIZE
147 }
148}
149
150#[derive(Debug, PartialEq)]
152pub struct AddSourceOperation {
153 pub(crate) advertiser_address_type: AddressType,
154 pub(crate) advertiser_address: [u8; ADDRESS_BYTE_SIZE],
156 pub(crate) advertising_sid: AdvertisingSetId,
157 pub(crate) broadcast_id: BroadcastId,
158 pub(crate) pa_sync: PaSync,
159 pub(crate) pa_interval: PeriodicAdvertisingInterval,
160 pub(crate) subgroups: Vec<BigSubgroup>,
161}
162
163impl AddSourceOperation {
164 const MIN_PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE
165 + AddressType::BYTE_SIZE
166 + ADDRESS_BYTE_SIZE
167 + AdvertisingSetId::BYTE_SIZE
168 + BroadcastId::BYTE_SIZE
169 + PA_SYNC_BYTE_SIZE
170 + PeriodicAdvertisingInterval::BYTE_SIZE
171 + NUM_SUBGROUPS_BYTE_SIZE;
172
173 pub fn new(
174 address_type: AddressType,
175 advertiser_address: [u8; ADDRESS_BYTE_SIZE],
176 advertising_sid: AdvertisingSetId,
177 broadcast_id: BroadcastId,
178 pa_sync: PaSync,
179 pa_interval: PeriodicAdvertisingInterval,
180 subgroups: Vec<BigSubgroup>,
181 ) -> Self {
182 AddSourceOperation {
183 advertiser_address_type: address_type,
184 advertiser_address,
185 advertising_sid,
186 broadcast_id: broadcast_id,
187 pa_sync,
188 pa_interval,
189 subgroups,
190 }
191 }
192}
193
194impl ControlPointOperation for AddSourceOperation {
195 fn opcode() -> ControlPointOpcode {
196 ControlPointOpcode::AddSource
197 }
198}
199
200impl Decodable for AddSourceOperation {
201 type Error = PacketError;
202
203 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
204 if buf.len() < Self::MIN_PACKET_SIZE {
205 return (Err(PacketError::UnexpectedDataLength), buf.len());
206 }
207
208 let decode_fn = || {
209 let _ = Self::check_opcode(buf[0])?;
210 let advertiser_address_type = AddressType::try_from(buf[1])?;
211 let mut advertiser_address = [0; ADDRESS_BYTE_SIZE];
212 advertiser_address.clone_from_slice(&buf[2..8]);
213 let advertising_sid = AdvertisingSetId::try_from(buf[8])?;
214 let broadcast_id = BroadcastId::decode(&buf[9..12]).0?;
215 let pa_sync = PaSync::try_from(buf[12])?;
216 let pa_interval =
217 PeriodicAdvertisingInterval(u16::from_le_bytes(buf[13..15].try_into().unwrap()));
218 let num_subgroups = buf[15] as usize;
219 let mut subgroups = Vec::new();
220
221 let mut idx: usize = 16;
222 for _i in 0..num_subgroups {
223 if buf.len() <= idx {
224 return Err(PacketError::UnexpectedDataLength);
225 }
226 let (decoded, consumed) = BigSubgroup::decode(&buf[idx..]);
227 subgroups.push(decoded?);
228 idx += consumed;
229 }
230 Ok((
231 Self {
232 advertiser_address_type,
233 advertiser_address,
234 advertising_sid,
235 broadcast_id,
236 pa_sync,
237 pa_interval,
238 subgroups,
239 },
240 idx,
241 ))
242 };
243
244 match decode_fn() {
245 Ok((result, consumed)) => (Ok(result), consumed),
246 Err(e) => (Err(e), buf.len()),
247 }
248 }
249}
250
251impl Encodable for AddSourceOperation {
252 type Error = PacketError;
253
254 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
255 if buf.len() < self.encoded_len() {
256 return Err(PacketError::BufferTooSmall);
257 }
258
259 buf[0] = Self::opcode() as u8;
260 buf[1] = self.advertiser_address_type as u8;
261 buf[2..8].copy_from_slice(&self.advertiser_address);
262 buf[8] = self.advertising_sid.value();
263 self.broadcast_id.encode(&mut buf[9..12])?;
264 buf[12] = u8::from(self.pa_sync);
265 buf[13..15].copy_from_slice(&self.pa_interval.0.to_le_bytes());
266 buf[15] = self
267 .subgroups
268 .len()
269 .try_into()
270 .map_err(|_| PacketError::InvalidParameter("Num_Subgroups".to_string()))?;
271 let mut idx = 16;
272 for s in &self.subgroups {
273 s.encode(&mut buf[idx..])?;
274 idx += s.encoded_len();
275 }
276 Ok(())
277 }
278
279 fn encoded_len(&self) -> core::primitive::usize {
280 Self::MIN_PACKET_SIZE + self.subgroups.iter().fold(0, |acc, g| acc + g.encoded_len())
281 }
282}
283
284#[derive(Debug, PartialEq)]
286pub struct ModifySourceOperation {
287 source_id: SourceId,
288 pa_sync: PaSync,
289 pa_interval: PeriodicAdvertisingInterval,
290 subgroups: Vec<BigSubgroup>,
291}
292
293impl ModifySourceOperation {
294 const MIN_PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE
295 + SOURCE_ID_BYTE_SIZE
296 + PA_SYNC_BYTE_SIZE
297 + PeriodicAdvertisingInterval::BYTE_SIZE
298 + NUM_SUBGROUPS_BYTE_SIZE;
299
300 pub fn new(
301 source_id: SourceId,
302 pa_sync: PaSync,
303 pa_interval: PeriodicAdvertisingInterval,
304 subgroups: Vec<BigSubgroup>,
305 ) -> Self {
306 ModifySourceOperation { source_id, pa_sync, pa_interval, subgroups }
307 }
308}
309
310impl ControlPointOperation for ModifySourceOperation {
311 fn opcode() -> ControlPointOpcode {
312 ControlPointOpcode::ModifySource
313 }
314}
315
316impl Decodable for ModifySourceOperation {
317 type Error = PacketError;
318
319 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
321 if buf.len() < Self::MIN_PACKET_SIZE {
322 return (Err(PacketError::UnexpectedDataLength), buf.len());
323 }
324 let decode_fn = || {
325 let _ = Self::check_opcode(buf[0])?;
326 let source_id = buf[1];
327 let pa_sync = PaSync::try_from(buf[2])?;
328 let pa_interval =
329 PeriodicAdvertisingInterval(u16::from_le_bytes(buf[3..5].try_into().unwrap()));
330 let num_subgroups = buf[5] as usize;
331 let mut subgroups = Vec::new();
332
333 let mut idx = 6;
334 for _i in 0..num_subgroups {
335 if buf.len() < idx + BigSubgroup::MIN_PACKET_SIZE {
336 return Err(PacketError::UnexpectedDataLength);
337 }
338 let decoded = BigSubgroup::decode(&buf[idx..]);
339 subgroups.push(decoded.0?);
340 idx += decoded.1;
341 }
342 Ok((Self { source_id, pa_sync, pa_interval, subgroups }, idx))
343 };
344
345 match decode_fn() {
346 Ok((obj, consumed)) => (Ok(obj), consumed),
347 Err(e) => (Err(e), buf.len()),
348 }
349 }
350}
351
352impl Encodable for ModifySourceOperation {
353 type Error = PacketError;
354
355 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
356 if buf.len() < self.encoded_len() {
357 return Err(PacketError::BufferTooSmall);
358 }
359
360 buf[0] = Self::opcode() as u8;
361 buf[1] = self.source_id;
362 buf[2] = u8::from(self.pa_sync);
363 buf[3..5].copy_from_slice(&self.pa_interval.0.to_le_bytes());
364 buf[5] = self
365 .subgroups
366 .len()
367 .try_into()
368 .map_err(|_| PacketError::InvalidParameter("Num_Subgroups".to_string()))?;
369 let mut idx = 6;
370 for s in &self.subgroups {
371 s.encode(&mut buf[idx..])?;
372 idx += s.encoded_len();
373 }
374 Ok(())
375 }
376
377 fn encoded_len(&self) -> core::primitive::usize {
378 Self::MIN_PACKET_SIZE + self.subgroups.iter().fold(0, |acc, g| acc + g.encoded_len())
379 }
380}
381
382#[derive(Debug, PartialEq)]
384pub struct SetBroadcastCodeOperation {
385 source_id: SourceId,
386 broadcast_code: [u8; 16],
387}
388
389impl SetBroadcastCodeOperation {
390 const BROADCAST_CODE_LEN: usize = 16;
391 const PACKET_SIZE: usize =
392 ControlPointOpcode::BYTE_SIZE + SOURCE_ID_BYTE_SIZE + Self::BROADCAST_CODE_LEN;
393
394 pub fn new(source_id: SourceId, broadcast_code: [u8; 16]) -> Self {
395 SetBroadcastCodeOperation { source_id, broadcast_code }
396 }
397}
398
399impl ControlPointOperation for SetBroadcastCodeOperation {
400 fn opcode() -> ControlPointOpcode {
401 ControlPointOpcode::SetBroadcastCode
402 }
403}
404
405impl Decodable for SetBroadcastCodeOperation {
406 type Error = PacketError;
407
408 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
410 if buf.len() < Self::PACKET_SIZE {
411 return (Err(PacketError::UnexpectedDataLength), buf.len());
412 }
413 let decode_fn = || {
414 let _ = Self::check_opcode(buf[0])?;
415 let source_id = buf[1];
416 let mut broadcast_code = [0; Self::BROADCAST_CODE_LEN];
417 broadcast_code.copy_from_slice(&buf[2..2 + Self::BROADCAST_CODE_LEN]);
418 Ok((Self { source_id, broadcast_code }, Self::PACKET_SIZE))
419 };
420
421 match decode_fn() {
422 Ok((obj, consumed)) => (Ok(obj), consumed),
423 Err(e) => (Err(e), buf.len()),
424 }
425 }
426}
427
428impl Encodable for SetBroadcastCodeOperation {
429 type Error = PacketError;
430
431 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
432 if buf.len() < self.encoded_len() {
433 return Err(PacketError::BufferTooSmall);
434 }
435
436 buf[0] = Self::opcode() as u8;
437 buf[1] = self.source_id;
438 buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(&self.broadcast_code);
439 Ok(())
440 }
441
442 fn encoded_len(&self) -> core::primitive::usize {
443 Self::PACKET_SIZE
444 }
445}
446
447#[derive(Debug, PartialEq)]
449pub struct RemoveSourceOperation(SourceId);
450
451impl RemoveSourceOperation {
452 const PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE + SOURCE_ID_BYTE_SIZE;
453
454 pub fn new(source_id: SourceId) -> Self {
455 RemoveSourceOperation(source_id)
456 }
457}
458
459impl ControlPointOperation for RemoveSourceOperation {
460 fn opcode() -> ControlPointOpcode {
461 ControlPointOpcode::RemoveSource
462 }
463}
464
465impl Decodable for RemoveSourceOperation {
466 type Error = PacketError;
467
468 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
470 if buf.len() < Self::PACKET_SIZE {
471 return (Err(PacketError::UnexpectedDataLength), buf.len());
472 }
473 let decode_fn = || {
474 let _ = Self::check_opcode(buf[0])?;
475 let source_id = buf[1];
476 Ok((RemoveSourceOperation(source_id), Self::PACKET_SIZE))
477 };
478 match decode_fn() {
479 Ok((obj, consumed)) => (Ok(obj), consumed),
480 Err(e) => (Err(e), buf.len()),
481 }
482 }
483}
484
485impl Encodable for RemoveSourceOperation {
486 type Error = PacketError;
487
488 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
489 if buf.len() < self.encoded_len() {
490 return Err(PacketError::BufferTooSmall);
491 }
492
493 buf[0] = Self::opcode() as u8;
494 buf[1] = self.0;
495 Ok(())
496 }
497
498 fn encoded_len(&self) -> core::primitive::usize {
499 Self::PACKET_SIZE
500 }
501}
502
503decodable_enum! {
504 pub enum PaSync<u8, bt_common::packet_encoding::Error, OutOfRange> {
505 DoNotSync = 0x00,
506 SyncPastAvailable = 0x01,
507 SyncPastUnavailable = 0x02,
508 }
509}
510
511impl FromStr for PaSync {
512 type Err = PacketError;
513
514 fn from_str(s: &str) -> Result<Self, Self::Err> {
515 match s {
516 "PaSyncOff" => Ok(PaSync::DoNotSync),
517 "PaSyncPast" => Ok(PaSync::SyncPastAvailable),
518 "PaSyncNoPast" => Ok(PaSync::SyncPastUnavailable),
519 _ => Err(PacketError::InvalidParameter(format!("invalid pa_sync: {s}"))),
520 }
521 }
522}
523
524#[derive(Clone, Debug, PartialEq)]
530pub struct BisSync(u32);
531
532impl BisSync {
533 const BYTE_SIZE: usize = 4;
534 const NO_PREFERENCE: u32 = 0xFFFFFFFF;
535
536 pub fn no_sync() -> BisSync {
538 BisSync(0)
539 }
540
541 pub fn synchronize_to_index(&mut self, bis_index: BisIndex) -> Result<(), PacketError> {
549 if bis_index < 1 || bis_index > 31 {
550 return Err(PacketError::OutOfRange);
551 }
552 let bit_mask = 0b1 << (bis_index - 1);
553
554 if self.0 == Self::NO_PREFERENCE {
555 self.0 = 0;
559 }
560 self.0 |= bit_mask;
561 Ok(())
562 }
563
564 pub fn sync(bis_indices: Vec<BisIndex>) -> Result<Self, PacketError> {
571 let mut new_sync = Self::no_sync();
572 for bis_index in bis_indices {
573 new_sync.synchronize_to_index(bis_index)?;
574 }
575 Ok(new_sync)
576 }
577}
578
579impl Default for BisSync {
580 fn default() -> Self {
581 Self(Self::NO_PREFERENCE)
582 }
583}
584
585impl From<BisSync> for u32 {
586 fn from(bis_sync: BisSync) -> u32 {
587 bis_sync.0
588 }
589}
590
591#[derive(Clone, Debug, PartialEq)]
592pub struct BigSubgroup {
593 pub(crate) bis_sync: BisSync,
594 pub(crate) metadata: Vec<Metadata>,
595}
596
597impl BigSubgroup {
598 const METADATA_LENGTH_BYTE_SIZE: usize = 1;
599 const MIN_PACKET_SIZE: usize = BisSync::BYTE_SIZE + Self::METADATA_LENGTH_BYTE_SIZE;
600
601 pub fn new(bis_sync: Option<BisSync>) -> Self {
602 Self { bis_sync: bis_sync.unwrap_or_default(), metadata: vec![] }
603 }
604
605 pub fn with_metadata(mut self, metadata: Vec<Metadata>) -> Self {
606 self.metadata = metadata;
607 self
608 }
609}
610
611impl Decodable for BigSubgroup {
612 type Error = PacketError;
613
614 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
615 if buf.len() < BigSubgroup::MIN_PACKET_SIZE {
616 return (Err(PacketError::UnexpectedDataLength), buf.len());
617 }
618 let decode_fn = || {
619 let bis_sync = u32::from_le_bytes(buf[0..4].try_into().unwrap());
620 let metadata_len = buf[4] as usize;
621
622 let mut start_idx = 5;
623 if buf.len() < start_idx + metadata_len {
624 return Err(PacketError::UnexpectedDataLength);
625 }
626
627 let (results_metadata, consumed_len) =
628 Metadata::decode_all(&buf[start_idx..start_idx + metadata_len]);
629 start_idx += consumed_len;
630 if start_idx != 5 + metadata_len {
631 return Err(PacketError::UnexpectedDataLength);
632 }
633 let metadata = results_metadata.into_iter().filter_map(Result::ok).collect();
635 Ok((BigSubgroup { bis_sync: BisSync(bis_sync), metadata }, start_idx))
636 };
637 match decode_fn() {
638 Ok((obj, consumed)) => (Ok(obj), consumed),
639 Err(e) => (Err(e), buf.len()),
640 }
641 }
642}
643
644impl Encodable for BigSubgroup {
645 type Error = PacketError;
646
647 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
648 if buf.len() < self.encoded_len() {
649 return Err(PacketError::BufferTooSmall);
650 }
651
652 buf[0..4].copy_from_slice(&u32::from(self.bis_sync.clone()).to_le_bytes());
653 let metadata_len = self
654 .metadata
655 .iter()
656 .fold(0, |acc, m| acc + m.encoded_len())
657 .try_into()
658 .map_err(|_| PacketError::InvalidParameter("Metadata".to_string()))?;
659 buf[4] = metadata_len;
660 let mut next_idx = 5;
661 for m in &self.metadata {
662 m.encode(&mut buf[next_idx..])
663 .map_err(|e| PacketError::InvalidParameter(format!("{e}")))?;
664 next_idx += m.encoded_len();
665 }
666 Ok(())
667 }
668
669 fn encoded_len(&self) -> core::primitive::usize {
670 Self::MIN_PACKET_SIZE + self.metadata.iter().map(Encodable::encoded_len).sum::<usize>()
671 }
672}
673
674#[derive(Clone, Debug, PartialEq)]
681pub enum BroadcastReceiveState {
682 Empty,
683 NonEmpty(ReceiveState),
684}
685
686impl BroadcastReceiveState {
687 pub fn is_empty(&self) -> bool {
688 *self == BroadcastReceiveState::Empty
689 }
690
691 pub fn broadcast_id(&self) -> Option<BroadcastId> {
692 match self {
693 BroadcastReceiveState::Empty => None,
694 BroadcastReceiveState::NonEmpty(state) => Some(state.broadcast_id),
695 }
696 }
697
698 pub fn has_same_broadcast_id(&self, other: &BroadcastReceiveState) -> bool {
699 match self {
700 BroadcastReceiveState::Empty => false,
701 BroadcastReceiveState::NonEmpty(this) => match other {
702 BroadcastReceiveState::Empty => false,
703 BroadcastReceiveState::NonEmpty(that) => this.broadcast_id == that.broadcast_id,
704 },
705 }
706 }
707}
708
709impl Decodable for BroadcastReceiveState {
710 type Error = PacketError;
711
712 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
713 if buf.len() == 0 {
714 return (Ok(Self::Empty), 0);
715 }
716 match ReceiveState::decode(&buf[..]) {
717 (Ok(state), consumed) => (Ok(Self::NonEmpty(state)), consumed),
718 (Err(e), consumed) => (Err(e), consumed),
719 }
720 }
721}
722
723impl Encodable for BroadcastReceiveState {
724 type Error = PacketError;
725
726 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
727 match self {
728 Self::Empty => Ok(()),
729 Self::NonEmpty(state) => state.encode(&mut buf[..]),
730 }
731 }
732
733 fn encoded_len(&self) -> core::primitive::usize {
734 match self {
735 Self::Empty => 0,
736 Self::NonEmpty(state) => state.encoded_len(),
737 }
738 }
739}
740
741#[derive(Clone, Debug, PartialEq)]
742pub struct ReceiveState {
743 pub(crate) source_id: SourceId,
744 pub(crate) source_address_type: AddressType,
745 pub(crate) source_address: [u8; ADDRESS_BYTE_SIZE],
747 pub(crate) source_adv_sid: AdvertisingSetId,
748 pub(crate) broadcast_id: BroadcastId,
749 pub(crate) pa_sync_state: PaSyncState,
750 pub(crate) big_encryption: EncryptionStatus,
752 pub(crate) subgroups: Vec<BigSubgroup>,
753}
754
755impl ReceiveState {
756 const MIN_PACKET_SIZE: usize = SOURCE_ID_BYTE_SIZE
757 + AddressType::BYTE_SIZE
758 + ADDRESS_BYTE_SIZE
759 + AdvertisingSetId::BYTE_SIZE
760 + BroadcastId::BYTE_SIZE
761 + PA_SYNC_BYTE_SIZE
762 + EncryptionStatus::MIN_PACKET_SIZE
763 + NUM_SUBGROUPS_BYTE_SIZE;
764
765 #[cfg(any(test, feature = "test-utils"))]
766 pub fn new(
767 source_id: u8,
768 source_address_type: AddressType,
769 source_address: [u8; ADDRESS_BYTE_SIZE],
770 source_adv_sid: AdvertisingSetId,
771 broadcast_id: BroadcastId,
772 pa_sync_state: PaSyncState,
773 big_encryption: EncryptionStatus,
774 subgroups: Vec<BigSubgroup>,
775 ) -> ReceiveState {
776 Self {
777 source_id,
778 source_address_type,
779 source_address,
780 source_adv_sid,
781 broadcast_id,
782 pa_sync_state,
783 big_encryption,
784 subgroups,
785 }
786 }
787
788 pub fn pa_sync_state(&self) -> PaSyncState {
789 self.pa_sync_state
790 }
791
792 pub fn big_encryption(&self) -> EncryptionStatus {
793 self.big_encryption
794 }
795
796 pub fn broadcast_id(&self) -> BroadcastId {
797 self.broadcast_id
798 }
799
800 pub fn source_id(&self) -> SourceId {
801 self.source_id
802 }
803}
804
805impl Decodable for ReceiveState {
806 type Error = PacketError;
807
808 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
809 if buf.len() < Self::MIN_PACKET_SIZE {
810 return (Err(PacketError::UnexpectedDataLength), buf.len());
811 }
812
813 let decode_fn = || {
814 let source_id = buf[0];
815 let source_address_type = AddressType::try_from(buf[1])?;
816 let mut source_address = [0; ADDRESS_BYTE_SIZE];
817 source_address.clone_from_slice(&buf[2..8]);
818 let source_adv_sid = AdvertisingSetId::try_from(buf[8])?;
819 let broadcast_id = BroadcastId::decode(&buf[9..12]).0?;
820 let pa_sync_state = PaSyncState::try_from(buf[12])?;
821
822 let big_encryption;
823 let mut idx = 13;
824 match EncryptionStatus::decode(&buf[13..]) {
825 (Ok(encryption), consumed) => {
826 big_encryption = encryption;
827 idx += consumed;
828 }
829 (Err(e), _) => {
830 return Err(e);
831 }
832 }
833 if buf.len() <= idx {
834 return Err(PacketError::UnexpectedDataLength);
835 }
836 let num_subgroups = buf[idx] as usize;
837 let mut subgroups = Vec::new();
838 idx += 1;
839 for _i in 0..num_subgroups {
840 if buf.len() <= idx {
841 return Err(PacketError::UnexpectedDataLength);
842 }
843 let (subgroup, consumed) = BigSubgroup::decode(&buf[idx..]);
844 subgroups.push(subgroup?);
845 idx += consumed;
846 }
847 Ok((
848 ReceiveState {
849 source_id,
850 source_address_type,
851 source_address,
852 source_adv_sid,
853 broadcast_id,
854 pa_sync_state,
855 big_encryption,
856 subgroups,
857 },
858 idx,
859 ))
860 };
861 match decode_fn() {
862 Ok((obj, consumed)) => (Ok(obj), consumed),
863 Err(e) => (Err(e), buf.len()),
864 }
865 }
866}
867
868impl Encodable for ReceiveState {
869 type Error = PacketError;
870
871 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
872 if buf.len() < self.encoded_len() {
873 return Err(PacketError::BufferTooSmall);
874 }
875
876 buf[0] = self.source_id;
877 buf[1] = self.source_address_type as u8;
878 buf[2..8].copy_from_slice(&self.source_address);
879 buf[8] = self.source_adv_sid.value();
880 self.broadcast_id.encode(&mut buf[9..12])?;
881 buf[12] = u8::from(self.pa_sync_state);
882 let mut idx = 13 + self.big_encryption.encoded_len();
883 self.big_encryption.encode(&mut buf[13..idx])?;
884 buf[idx] = self
885 .subgroups
886 .len()
887 .try_into()
888 .map_err(|_| PacketError::InvalidParameter("Metadata".to_string()))?;
889 idx += 1;
890 for s in &self.subgroups {
891 s.encode(&mut buf[idx..])?;
892 idx += s.encoded_len();
893 }
894 Ok(())
895 }
896
897 fn encoded_len(&self) -> core::primitive::usize {
898 SOURCE_ID_BYTE_SIZE
902 + AddressType::BYTE_SIZE
903 + self.source_address.len()
904 + AdvertisingSetId::BYTE_SIZE
905 + self.broadcast_id.encoded_len()
906 + PA_SYNC_BYTE_SIZE
907 + self.big_encryption.encoded_len()
908 + NUM_SUBGROUPS_BYTE_SIZE
909 + self.subgroups.iter().map(Encodable::encoded_len).sum::<usize>()
910 }
911}
912
913decodable_enum! {
914 pub enum PaSyncState<u8, bt_common::packet_encoding::Error, OutOfRange> {
915 NotSynced = 0x00,
916 SyncInfoRequest = 0x01,
917 Synced = 0x02,
918 FailedToSync = 0x03,
919 NoPast = 0x04,
920 }
921}
922
923#[derive(Clone, Copy, Debug, PartialEq)]
926pub enum EncryptionStatus {
927 NotEncrypted,
928 BroadcastCodeRequired,
929 Decrypting,
930 BadCode([u8; 16]),
931}
932
933impl EncryptionStatus {
934 const MIN_PACKET_SIZE: usize = 1;
936
937 pub const fn raw_value(self) -> u8 {
940 match self {
941 EncryptionStatus::NotEncrypted => 0x00,
942 EncryptionStatus::BroadcastCodeRequired => 0x01,
943 EncryptionStatus::Decrypting => 0x02,
944 EncryptionStatus::BadCode(_) => 0x03,
945 }
946 }
947}
948
949impl Decodable for EncryptionStatus {
950 type Error = PacketError;
951
952 fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
953 if buf.len() < 1 {
954 return (Err(PacketError::UnexpectedDataLength), buf.len());
955 }
956 match buf[0] {
957 0x00 => (Ok(Self::NotEncrypted), 1),
958 0x01 => (Ok(Self::BroadcastCodeRequired), 1),
959 0x02 => (Ok(Self::Decrypting), 1),
960 0x03 => {
961 if buf.len() < 17 {
962 return (Err(PacketError::UnexpectedDataLength), buf.len());
963 }
964 (Ok(Self::BadCode(buf[1..17].try_into().unwrap())), 17)
965 }
966 _ => (Err(PacketError::OutOfRange), buf.len()),
967 }
968 }
969}
970
971impl Encodable for EncryptionStatus {
972 type Error = PacketError;
973
974 fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
975 if buf.len() < self.encoded_len() {
976 return Err(PacketError::BufferTooSmall);
977 }
978
979 buf[0] = self.raw_value();
980 match self {
981 EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code),
982 _ => {}
983 }
984 Ok(())
985 }
986
987 fn encoded_len(&self) -> core::primitive::usize {
988 match self {
989 EncryptionStatus::BadCode(_) => 1 + 16,
992 _ => 1,
993 }
994 }
995}
996
997#[cfg(test)]
998mod tests {
999 use super::*;
1000
1001 use bt_common::generic_audio::ContextType;
1002
1003 #[test]
1004 fn encryption_status_enum() {
1005 let not_encrypted = EncryptionStatus::NotEncrypted;
1006 let encrypted = EncryptionStatus::BroadcastCodeRequired;
1007 let decrypting = EncryptionStatus::Decrypting;
1008 let bad_code = EncryptionStatus::BadCode([
1009 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1010 0x02, 0x01,
1011 ]);
1012
1013 assert_eq!(0x00, not_encrypted.raw_value());
1014 assert_eq!(0x01, encrypted.raw_value());
1015 assert_eq!(0x02, decrypting.raw_value());
1016 assert_eq!(0x03, bad_code.raw_value());
1017 }
1018
1019 #[test]
1020 fn encryption_status() {
1021 let not_encrypted = EncryptionStatus::NotEncrypted;
1023 assert_eq!(not_encrypted.encoded_len(), 1);
1024 let mut buf = vec![0; not_encrypted.encoded_len()];
1025 let _ = not_encrypted.encode(&mut buf[..]).expect("should not fail");
1026
1027 let bytes = vec![0x00];
1028 assert_eq!(buf, bytes);
1029
1030 let (decoded, len) = EncryptionStatus::decode(&bytes);
1032 assert_eq!(decoded, Ok(not_encrypted));
1033 assert_eq!(len, 1);
1034
1035 let bad_code = EncryptionStatus::BadCode([
1037 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1038 0x02, 0x01,
1039 ]);
1040 assert_eq!(bad_code.encoded_len(), 17);
1041 let mut buf = vec![0; bad_code.encoded_len()];
1042 let _ = bad_code.encode(&mut buf[..]).expect("should not fail");
1043
1044 let bytes = vec![
1045 0x03, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
1046 0x03, 0x02, 0x01,
1047 ];
1048 assert_eq!(buf, bytes);
1049
1050 let (decoded, len) = EncryptionStatus::decode(&bytes);
1052 assert_eq!(decoded, Ok(bad_code));
1053 assert_eq!(len, 17);
1054 }
1055
1056 #[test]
1057 fn invalid_encryption_status() {
1058 let not_encrypted = EncryptionStatus::NotEncrypted;
1060 let mut buf = vec![];
1061 let _ = not_encrypted.encode(&mut buf[..]).expect_err("should fail");
1062
1063 let bad_code = EncryptionStatus::BadCode([
1065 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1066 0x02, 0x01,
1067 ]);
1068 let mut buf = vec![0; 1];
1069 let _ = bad_code.encode(&mut buf[..]).expect_err("should fail");
1070
1071 let buf = vec![];
1073 let _ = EncryptionStatus::decode(&buf).0.expect_err("should fail");
1074
1075 let buf = vec![0x03];
1077 let _ = EncryptionStatus::decode(&buf).0.expect_err("should fail");
1078 }
1079
1080 #[test]
1081 fn bis_sync_sync() {
1082 let bis_sync = BisSync::sync(vec![1, 6, 31]).expect("should succeed");
1083 assert_eq!(u32::from(bis_sync), 0x40000021);
1084
1085 let bis_sync_empty = BisSync::sync(vec![]).expect("should succeed");
1086 assert_eq!(u32::from(bis_sync_empty), 0);
1087 }
1088
1089 #[test]
1090 fn invalid_bis_sync() {
1091 BisSync::sync(vec![0]).expect_err("should fail");
1092 BisSync::sync(vec![32]).expect_err("should fail");
1093 }
1094
1095 #[test]
1096 fn synchronize_to_index() {
1097 let mut bis_sync = BisSync::no_sync();
1098 assert_eq!(u32::from(bis_sync.clone()), 0);
1099
1100 bis_sync.synchronize_to_index(1).expect("should succeed");
1101 assert_eq!(u32::from(bis_sync.clone()), 0x1);
1102
1103 bis_sync.synchronize_to_index(31).expect("should succeed");
1104 assert_eq!(u32::from(bis_sync.clone()), 0x40000001);
1105
1106 bis_sync.synchronize_to_index(0).expect_err("should fail");
1107 bis_sync.synchronize_to_index(32).expect_err("should fail");
1108 }
1109
1110 #[test]
1111 fn synchronize_to_index_from_default() {
1112 let mut bis_sync_default = BisSync::default();
1113 assert_eq!(u32::from(bis_sync_default.clone()), 0xFFFFFFFF);
1114
1115 bis_sync_default.synchronize_to_index(1).expect("should succeed");
1118 assert_eq!(u32::from(bis_sync_default.clone()), 0x1);
1119
1120 bis_sync_default.synchronize_to_index(6).expect("should succeed");
1122 assert_eq!(u32::from(bis_sync_default), 0x21);
1123 }
1124
1125 #[test]
1126 fn pa_sync_from_str() {
1127 let sync = PaSync::from_str("PaSyncOff").expect("should succeed");
1128 assert_eq!(sync, PaSync::DoNotSync);
1129 let sync = PaSync::from_str("PaSyncPast").expect("should succeed");
1130 assert_eq!(sync, PaSync::SyncPastAvailable);
1131 let sync = PaSync::from_str("PaSyncNoPast").expect("should succeed");
1132 assert_eq!(sync, PaSync::SyncPastUnavailable);
1133 PaSync::from_str("invalid").expect_err("should fail");
1134 }
1135
1136 #[test]
1137 fn remote_scan_stopped() {
1138 let stopped = RemoteScanStoppedOperation;
1140 assert_eq!(stopped.encoded_len(), 1);
1141 let mut buf = vec![0u8; stopped.encoded_len()];
1142 stopped.encode(&mut buf[..]).expect("shoud succeed");
1143
1144 let bytes = vec![0x00];
1145 assert_eq!(buf, bytes);
1146
1147 let (decoded, len) = RemoteScanStoppedOperation::decode(&bytes);
1149 assert_eq!(decoded, Ok(stopped));
1150 assert_eq!(len, 1);
1151 assert_eq!(
1152 RemoteScanStoppedOperation::decode(&[]).0,
1153 Err(PacketError::UnexpectedDataLength)
1154 );
1155 }
1156
1157 #[test]
1158 fn remote_scan_started() {
1159 let started = RemoteScanStartedOperation;
1161 assert_eq!(started.encoded_len(), 1);
1162 let mut buf = vec![0u8; started.encoded_len()];
1163 started.encode(&mut buf[..]).expect("shoud succeed");
1164
1165 let bytes = vec![0x01];
1166 assert_eq!(buf, vec![0x01]);
1167
1168 let (decoded, len) = RemoteScanStartedOperation::decode(&bytes);
1170 assert_eq!(decoded, Ok(started));
1171 assert_eq!(len, 1);
1172 }
1173
1174 #[test]
1175 fn add_source_without_subgroups() {
1176 let op = AddSourceOperation::new(
1178 AddressType::Public,
1179 [0x04, 0x10, 0x00, 0x00, 0x00, 0x00],
1180 AdvertisingSetId::try_from(1).unwrap(),
1181 BroadcastId::try_from(0x11).unwrap(),
1182 PaSync::DoNotSync,
1183 PeriodicAdvertisingInterval::unknown(),
1184 vec![],
1185 );
1186 assert_eq!(op.encoded_len(), 16);
1187 let mut buf = vec![0u8; op.encoded_len()];
1188 op.encode(&mut buf[..]).expect("shoud succeed");
1189
1190 let bytes = vec![
1191 0x02, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0xFF,
1192 0xFF, 0x00,
1193 ];
1194 assert_eq!(buf, bytes);
1195
1196 let (decoded, len) = AddSourceOperation::decode(&bytes);
1198 assert_eq!(decoded, Ok(op));
1199 assert_eq!(len, 16);
1200 }
1201
1202 #[test]
1203 fn add_source_with_subgroups() {
1204 let subgroups = vec![BigSubgroup::new(None).with_metadata(vec![
1206 Metadata::PreferredAudioContexts(vec![ContextType::Media, ContextType::Game]), Metadata::ProgramInfo("test".to_string()), ])];
1209 let op = AddSourceOperation::new(
1210 AddressType::Random,
1211 [0x04, 0x10, 0x00, 0x00, 0x00, 0x00],
1212 AdvertisingSetId::try_from(1).unwrap(),
1213 BroadcastId::try_from(0x11).unwrap(),
1214 PaSync::SyncPastAvailable,
1215 PeriodicAdvertisingInterval::unknown(),
1216 subgroups,
1217 );
1218 assert_eq!(op.encoded_len(), 31); let mut buf = vec![0u8; op.encoded_len()];
1220 op.encode(&mut buf[..]).expect("shoud succeed");
1221
1222 let bytes = vec![
1223 0x02, 0x01, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, 0xFF,
1224 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x03, 0x01, 0x0C, 0x00, 0x05, 0x03, 0x74, 0x65, 0x73, 0x074, ];
1228 assert_eq!(buf, bytes);
1229
1230 let (decoded, len) = AddSourceOperation::decode(&bytes);
1232 assert_eq!(decoded, Ok(op));
1233 assert_eq!(len, 31);
1234 }
1235
1236 #[test]
1237 fn invalid_advertising_sid_decoding() {
1238 let invalid_add_source_bytes = vec![
1240 0x02, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xFF,
1241 0xFF, 0x00,
1242 ];
1243 let (decoded, _) = AddSourceOperation::decode(&invalid_add_source_bytes);
1244 assert_eq!(decoded, Err(PacketError::OutOfRange));
1245
1246 let invalid_receive_state_bytes = vec![
1248 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x10, 0x03, 0x02, 0x01, 0x02, 0x00,
1249 0x00,
1250 ];
1251 let (decoded, _) = BroadcastReceiveState::decode(&invalid_receive_state_bytes);
1252 assert_eq!(decoded, Err(PacketError::OutOfRange));
1253 }
1254
1255 #[test]
1256 fn modify_source_without_subgroups() {
1257 let op = ModifySourceOperation::new(
1259 0x0A,
1260 PaSync::SyncPastAvailable,
1261 PeriodicAdvertisingInterval(0x1004),
1262 vec![],
1263 );
1264 assert_eq!(op.encoded_len(), 6);
1265 let mut buf = vec![0u8; op.encoded_len()];
1266 op.encode(&mut buf[..]).expect("shoud succeed");
1267
1268 let bytes = vec![0x03, 0x0A, 0x01, 0x04, 0x10, 0x00];
1269 assert_eq!(buf, bytes);
1270
1271 let (decoded, len) = ModifySourceOperation::decode(&bytes);
1273 assert_eq!(decoded, Ok(op));
1274 assert_eq!(len, 6);
1275 }
1276
1277 #[test]
1278 fn modify_source_with_subgroups() {
1279 let subgroups = vec![
1281 BigSubgroup::new(None).with_metadata(vec![Metadata::ParentalRating(Rating::all_age())]), BigSubgroup::new(Some(BisSync(0x000000FE)))
1283 .with_metadata(vec![Metadata::BroadcastAudioImmediateRenderingFlag]), ];
1285 let op = ModifySourceOperation::new(
1286 0x0B,
1287 PaSync::DoNotSync,
1288 PeriodicAdvertisingInterval::unknown(),
1289 subgroups,
1290 );
1291 assert_eq!(op.encoded_len(), 21); let mut buf = vec![0u8; op.encoded_len()];
1293 op.encode(&mut buf[..]).expect("shoud succeed");
1294
1295 let bytes = vec![
1296 0x03, 0x0B, 0x00, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x02, 0x06,
1297 0x01, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x01, 0x09, ];
1300 assert_eq!(buf, bytes);
1301
1302 let (decoded, len) = ModifySourceOperation::decode(&bytes);
1304 assert_eq!(decoded, Ok(op));
1305 assert_eq!(len, 21);
1306 }
1307
1308 #[test]
1309 fn set_broadcast_code() {
1310 let op = SetBroadcastCodeOperation::new(
1312 0x0A,
1313 [
1314 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14,
1315 0x15, 0x16,
1316 ],
1317 );
1318 assert_eq!(op.encoded_len(), 18);
1319 let mut buf = vec![0; op.encoded_len()];
1320 op.encode(&mut buf[..]).expect("should succeed");
1321
1322 let bytes = vec![
1323 0x04, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
1324 0x13, 0x14, 0x15, 0x16,
1325 ];
1326 assert_eq!(buf, bytes);
1327
1328 let (decoded, len) = SetBroadcastCodeOperation::decode(&bytes);
1330 assert_eq!(decoded, Ok(op));
1331 assert_eq!(len, 18);
1332 }
1333
1334 #[test]
1335 fn remove_source() {
1336 let op = RemoveSourceOperation::new(0x0A);
1338 assert_eq!(op.encoded_len(), 2);
1339 let mut buf = vec![0; op.encoded_len()];
1340 op.encode(&mut buf[..]).expect("should succeed");
1341
1342 let bytes = vec![0x05, 0x0A];
1343 assert_eq!(buf, bytes);
1344
1345 let (decoded, len) = RemoveSourceOperation::decode(&bytes);
1347 assert_eq!(decoded, Ok(op));
1348 assert_eq!(len, 2);
1349 }
1350
1351 #[test]
1352 fn broadcast_receive_state_without_subgroups() {
1353 let state = BroadcastReceiveState::NonEmpty(ReceiveState {
1355 source_id: 0x01,
1356 source_address_type: AddressType::Public,
1357 source_address: [0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A],
1358 source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(),
1359 broadcast_id: BroadcastId::try_from(0x00010203).unwrap(),
1360 pa_sync_state: PaSyncState::Synced,
1361 big_encryption: EncryptionStatus::BadCode([
1362 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x7, 0x06, 0x05, 0x04, 0x03,
1363 0x02, 0x01,
1364 ]),
1365 subgroups: vec![],
1366 });
1367 assert_eq!(state.encoded_len(), 31);
1368 let mut buf = vec![0; state.encoded_len()];
1369 state.encode(&mut buf[..]).expect("should succeed");
1370
1371 let bytes = vec![
1372 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x01, 0x03, 0x02, 0x01, 0x02, 0x03,
1373 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1374 0x02, 0x01, 0x00,
1376 ];
1377 assert_eq!(buf, bytes);
1378
1379 let (decoded, len) = BroadcastReceiveState::decode(&bytes);
1381 assert_eq!(decoded, Ok(state));
1382 assert_eq!(len, 31);
1383 }
1384
1385 #[test]
1386 fn broadcast_receive_state_with_subgroups() {
1387 let state = BroadcastReceiveState::NonEmpty(ReceiveState {
1389 source_id: 0x01,
1390 source_address_type: AddressType::Random,
1391 source_address: [0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A],
1392 source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(),
1393 broadcast_id: BroadcastId::try_from(0x00010203).unwrap(),
1394 pa_sync_state: PaSyncState::NotSynced,
1395 big_encryption: EncryptionStatus::NotEncrypted,
1396 subgroups: vec![BigSubgroup::new(None)
1397 .with_metadata(vec![Metadata::ParentalRating(Rating::AllAge)]) ],
1398 });
1399 assert_eq!(state.encoded_len(), 23);
1400 let mut buf = vec![0; state.encoded_len()];
1401 state.encode(&mut buf[..]).expect("should succeed");
1402
1403 let bytes = vec![
1404 0x01, 0x01, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x01, 0x03, 0x02, 0x01, 0x00, 0x00,
1405 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x02, 0x06, 0x01, ];
1408 assert_eq!(buf, bytes);
1409
1410 let (decoded, len) = BroadcastReceiveState::decode(&bytes);
1412 assert_eq!(decoded, Ok(state));
1413 assert_eq!(len, 23);
1414 }
1415}