rust/bt-bap: Use BroadcastCode type

Migrate all callsites in bt-bass and bt-broadcast-assistant from raw
[u8; 16] byte arrays to the strongly typed BroadcastCode struct for
consistency and type safety.

Bug: 539983871
Test: cargo test, ./presubmit.sh
Change-Id: I954bd6da90c71f9e12141d58af4d5f9430bfdd68
Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/3480
diff --git a/rust/bt-bap/src/types.rs b/rust/bt-bap/src/types.rs
index 5e62c73..7f768e7 100644
--- a/rust/bt-bap/src/types.rs
+++ b/rust/bt-bap/src/types.rs
@@ -88,14 +88,24 @@
 /// A 16-octet (128-bit) Broadcast Code used for decrypting encrypted
 /// Broadcast Audio Streams. See BAP v1.0.1 Section 3.7.2.2 for more details.
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct BroadcastCode(pub [u8; 16]);
+pub struct BroadcastCode([u8; 16]);
 
 impl BroadcastCode {
     pub const BYTE_SIZE: usize = 16;
 
-    pub fn new(raw_value: [u8; 16]) -> Self {
+    pub const fn new(raw_value: [u8; 16]) -> Self {
         Self(raw_value)
     }
+
+    pub const fn bytes(&self) -> &[u8; 16] {
+        &self.0
+    }
+}
+
+impl From<BroadcastCode> for [u8; 16] {
+    fn from(value: BroadcastCode) -> Self {
+        value.0
+    }
 }
 
 /// To associate a PA, used to expose broadcast Audio Stream parameters, with a
diff --git a/rust/bt-bass/src/client.rs b/rust/bt-bass/src/client.rs
index a1188c2..9532581 100644
--- a/rust/bt-bass/src/client.rs
+++ b/rust/bt-bass/src/client.rs
@@ -93,7 +93,7 @@
     broadcast_sources: Arc<Mutex<KnownBroadcastSources>>,
     /// Keeps track of the broadcast codes that were sent to the remote BASS
     /// server.
-    broadcast_codes: Arc<Mutex<HashMap<SourceId, [u8; 16]>>>,
+    broadcast_codes: Arc<Mutex<HashMap<SourceId, BroadcastCode>>>,
     // GATT notification streams for BRS characteristic value changes.
     notification_streams: Option<
         SelectAll<BoxStream<'static, Result<CharacteristicNotification, bt_gatt::types::Error>>>,
@@ -367,11 +367,11 @@
     pub async fn set_broadcast_code(
         &self,
         broadcast_id: BroadcastId,
-        broadcast_code: [u8; 16],
+        broadcast_code: BroadcastCode,
     ) -> Result<(), Error> {
         let source_id = self.get_source_id(&broadcast_id)?;
 
-        let op = SetBroadcastCodeOperation::new(source_id, BroadcastCode::new(broadcast_code));
+        let op = SetBroadcastCodeOperation::new(source_id, broadcast_code);
         self.write_to_bascp(op).await?;
 
         // Save the broadcast code we sent.
@@ -979,8 +979,10 @@
         );
 
         let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
-        let set_code_fut =
-            client.set_broadcast_code(BroadcastId::try_from(0x030201).unwrap(), [1; 16]);
+        let set_code_fut = client.set_broadcast_code(
+            BroadcastId::try_from(0x030201).unwrap(),
+            BroadcastCode::new([1; 16]),
+        );
         pin_mut!(set_code_fut);
         let polled = set_code_fut.poll_unpin(&mut noop_cx);
         assert_matches!(polled, Poll::Ready(Ok(_)));
@@ -991,8 +993,10 @@
         let (client, _) = setup_client();
 
         let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
-        let set_code_fut =
-            client.set_broadcast_code(BroadcastId::try_from(0x030201).unwrap(), [1; 16]);
+        let set_code_fut = client.set_broadcast_code(
+            BroadcastId::try_from(0x030201).unwrap(),
+            BroadcastCode::new([1; 16]),
+        );
         pin_mut!(set_code_fut);
         let polled = set_code_fut.poll_unpin(&mut noop_cx);
 
diff --git a/rust/bt-bass/src/client/event.rs b/rust/bt-bass/src/client/event.rs
index f7ad10b..6dd6e3f 100644
--- a/rust/bt-bass/src/client/event.rs
+++ b/rust/bt-bass/src/client/event.rs
@@ -10,7 +10,7 @@
 use futures::{Stream, StreamExt};
 use parking_lot::Mutex;
 
-use bt_bap::types::BroadcastId;
+use bt_bap::types::{BroadcastCode, BroadcastId};
 use bt_common::packet_encoding::Decodable;
 use bt_gatt::client::CharacteristicNotification;
 use bt_gatt::types::Error as BtGattError;
@@ -33,7 +33,7 @@
     // BASS server requires code to since the BIS is encrypted.
     BroadcastCodeRequired(BroadcastId),
     // BASS server failed to decrypt BIS using the previously provided code.
-    InvalidBroadcastCode(BroadcastId, [u8; 16]),
+    InvalidBroadcastCode(BroadcastId, BroadcastCode),
     // BASS server has autonomously synchronized to a BIS that is encrypted, and the server
     // has the correct encryption key to decrypt the BIS.
     Decrypting(BroadcastId),
@@ -64,7 +64,7 @@
             }
             EncryptionStatus::Decrypting => events.push(Event::Decrypting(broadcast_id)),
             EncryptionStatus::BadCode(code) => {
-                events.push(Event::InvalidBroadcastCode(broadcast_id, code.clone()))
+                events.push(Event::InvalidBroadcastCode(broadcast_id, code))
             }
             _ => {}
         };
@@ -221,8 +221,9 @@
         let mut event_streams = EventStream::new(streams, source_tracker);
 
         // Send notifications to underlying streams.
-        let bad_code_status =
-            EncryptionStatus::BadCode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+        let bad_code_status = EncryptionStatus::BadCode(BroadcastCode::new([
+            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+        ]));
         #[rustfmt::skip]
         sender1
             .unbounded_send(Ok(CharacteristicNotification {
@@ -260,7 +261,7 @@
         let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
         let polled = event_streams.poll_next_unpin(&mut noop_cx);
         assert_matches!(polled, Poll::Ready(Some(Ok(event))) => {
-            assert_eq!(event, Event::AddedBroadcastSource(BroadcastId::try_from(0x030201).unwrap(), PaSyncState::FailedToSync, EncryptionStatus::BadCode([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16])));
+            assert_eq!(event, Event::AddedBroadcastSource(BroadcastId::try_from(0x030201).unwrap(), PaSyncState::FailedToSync, EncryptionStatus::BadCode(BroadcastCode::new([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]))));
         });
 
         let polled = event_streams.poll_next_unpin(&mut noop_cx);
diff --git a/rust/bt-bass/src/types.rs b/rust/bt-bass/src/types.rs
index 64bf76c..8b1d3cf 100644
--- a/rust/bt-bass/src/types.rs
+++ b/rust/bt-bass/src/types.rs
@@ -442,7 +442,7 @@
 
         buf[0] = Self::opcode() as u8;
         buf[1] = self.source_id;
-        buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(&self.broadcast_code.0);
+        buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(self.broadcast_code.bytes());
         Ok(())
     }
 
@@ -944,7 +944,7 @@
     NotEncrypted,
     BroadcastCodeRequired,
     Decrypting,
-    BadCode([u8; 16]),
+    BadCode(BroadcastCode),
 }
 
 impl EncryptionStatus {
@@ -978,7 +978,7 @@
                 if buf.len() < 17 {
                     return (Err(PacketError::UnexpectedDataLength), buf.len());
                 }
-                (Ok(Self::BadCode(buf[1..17].try_into().unwrap())), 17)
+                (Ok(Self::BadCode(BroadcastCode::new(buf[1..17].try_into().unwrap()))), 17)
             }
             _ => (Err(PacketError::OutOfRange), buf.len()),
         }
@@ -995,7 +995,7 @@
 
         buf[0] = self.raw_value();
         match self {
-            EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code),
+            EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code.bytes()),
             _ => {}
         }
         Ok(())
@@ -1022,10 +1022,10 @@
         let not_encrypted = EncryptionStatus::NotEncrypted;
         let encrypted = EncryptionStatus::BroadcastCodeRequired;
         let decrypting = EncryptionStatus::Decrypting;
-        let bad_code = EncryptionStatus::BadCode([
+        let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([
             0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
             0x02, 0x01,
-        ]);
+        ]));
 
         assert_eq!(0x00, not_encrypted.raw_value());
         assert_eq!(0x01, encrypted.raw_value());
@@ -1050,10 +1050,10 @@
         assert_eq!(len, 1);
 
         // Encoding bad code status with code.
-        let bad_code = EncryptionStatus::BadCode([
+        let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([
             0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
             0x02, 0x01,
-        ]);
+        ]));
         assert_eq!(bad_code.encoded_len(), 17);
         let mut buf = vec![0; bad_code.encoded_len()];
         let _ = bad_code.encode(&mut buf[..]).expect("should not fail");
@@ -1078,10 +1078,10 @@
         let _ = not_encrypted.encode(&mut buf[..]).expect_err("should fail");
 
         // Not enough buffer space for encoding.
-        let bad_code = EncryptionStatus::BadCode([
+        let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([
             0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
             0x02, 0x01,
-        ]);
+        ]));
         let mut buf = vec![0; 1];
         let _ = bad_code.encode(&mut buf[..]).expect_err("should fail");
 
@@ -1375,10 +1375,10 @@
             source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(),
             broadcast_id: BroadcastId::try_from(0x00010203).unwrap(),
             pa_sync_state: PaSyncState::Synced,
-            big_encryption: EncryptionStatus::BadCode([
-                0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x7, 0x06, 0x05, 0x04, 0x03,
+            big_encryption: EncryptionStatus::BadCode(BroadcastCode::new([
+                0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
                 0x02, 0x01,
-            ]),
+            ])),
             subgroups: vec![],
         });
         assert_eq!(state.encoded_len(), 31);
diff --git a/rust/bt-broadcast-assistant/src/assistant/peer.rs b/rust/bt-broadcast-assistant/src/assistant/peer.rs
index 2527fb6..8c5860d 100644
--- a/rust/bt-broadcast-assistant/src/assistant/peer.rs
+++ b/rust/bt-broadcast-assistant/src/assistant/peer.rs
@@ -8,7 +8,7 @@
 use std::sync::Arc;
 use thiserror::Error;
 
-use bt_bap::types::BroadcastId;
+use bt_bap::types::{BroadcastCode, BroadcastId};
 use bt_bass::client::error::Error as BassClientError;
 use bt_bass::client::event::Event as BassEvent;
 use bt_bass::client::BroadcastAudioScanServiceClient;
@@ -84,7 +84,7 @@
     pub async fn send_broadcast_code(
         &self,
         broadcast_id: BroadcastId,
-        broadcast_code: [u8; 16],
+        broadcast_code: BroadcastCode,
     ) -> Result<(), Error> {
         self.bass.set_broadcast_code(broadcast_id, broadcast_code).await.map_err(Into::into)
     }
diff --git a/rust/bt-broadcast-assistant/src/debug.rs b/rust/bt-broadcast-assistant/src/debug.rs
index b369c4e..b9d933c 100644
--- a/rust/bt-broadcast-assistant/src/debug.rs
+++ b/rust/bt-broadcast-assistant/src/debug.rs
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use bt_bap::types::BroadcastId;
+use bt_bap::types::{BroadcastCode, BroadcastId};
 use bt_bass::client::error::Error as BassClientError;
 use bt_bass::client::event::Event as BassEvent;
 use bt_bass::types::{BisSync, PaSync, SubgroupIndex};
@@ -192,7 +192,7 @@
 /// The string is UTF-8 encoded and then padded with zeros on the right to a
 /// total length of 16 bytes. This result is a little-endian byte array
 /// equivalent to a 128-bit value.
-fn passcode_to_broadcast_code(passcode: &str) -> Result<[u8; 16], String> {
+fn passcode_to_broadcast_code(passcode: &str) -> Result<BroadcastCode, String> {
     if passcode.is_empty() {
         return Err("invalid broadcast code: passcode cannot be empty".to_string());
     }
@@ -206,7 +206,7 @@
     }
     let mut broadcast_code = [0u8; 16];
     broadcast_code[..code.len()].copy_from_slice(code);
-    Ok(broadcast_code)
+    Ok(BroadcastCode::new(broadcast_code))
 }
 
 impl<T: bt_gatt::GattTypes + 'static, R: GetPeerAddr> CommandRunner for AssistantDebug<T, R>
@@ -607,20 +607,20 @@
         // UTF-8 string that is less than 16 bytes.
         // Source of truth test case from Bluetooth Spec.
         let code = "Børne House";
-        let expected = [
+        let expected = BroadcastCode::new([
             0x42, 0xc3, 0xb8, 0x72, 0x6e, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x00,
             0x00, 0x00,
-        ];
+        ]);
         let actual = passcode_to_broadcast_code(code).expect("should succeed");
         assert_eq!(actual, expected);
-        assert_eq!(u128::from_le_bytes(actual), 0x00000000_6573756F_4820656E_72B8C342);
+        assert_eq!(u128::from_le_bytes(*actual.bytes()), 0x00000000_6573756F_4820656E_72B8C342);
 
         // Valid ASCII passcode, exactly 16 bytes.
         let code = "1234567890123456";
-        let expected = [
+        let expected = BroadcastCode::new([
             0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34,
             0x35, 0x36,
-        ];
+        ]);
         assert_eq!(passcode_to_broadcast_code(code).unwrap(), expected);
 
         // Invalid passcode, over 16 bytes.