Skip to main content

bt_bass/
types.rs

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