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