[rust][bt-pacs] Parse Metadata

Bug: b/308483293
Change-Id: I4529ae241c2203e37dc7fd5baa3237cb12e9a0e4
Reviewed-on: https://bluetooth-review.git.corp.google.com/c/bluetooth/+/1480
Reviewed-by: Dayeong Lee <dayeonglee@google.com>
diff --git a/rust/bt-pacs/src/lib.rs b/rust/bt-pacs/src/lib.rs
index b371697..72e9ecf 100644
--- a/rust/bt-pacs/src/lib.rs
+++ b/rust/bt-pacs/src/lib.rs
@@ -4,6 +4,7 @@
 
 use bt_common::core::ltv::LtValue;
 use bt_common::generic_audio::codec_capabilities::CodecCapability;
+use bt_common::generic_audio::metadata_ltv::Metadata;
 use bt_common::generic_audio::{AudioLocation, ContextType};
 use bt_common::packet_encoding::Decodable;
 use bt_common::Uuid;
@@ -52,7 +53,7 @@
     pub codec_id: CodecId,
     pub codec_specific_capabilities: Vec<CodecCapability>,
     // TODO: Actually parse the metadata once Metadata
-    pub metadata: (),
+    pub metadata: Vec<Metadata>,
 }
 
 impl bt_common::packet_encoding::Decodable for PacRecord {
@@ -72,20 +73,19 @@
         let codec_specific_capabilities = results.into_iter().filter_map(Result::ok).collect();
         idx += consumed;
 
-        let metadata_length = buf[idx];
+        let metadata_length = buf[idx] as usize;
         idx += 1;
-        // TODO: Actually parse the Metadata when the type is included in bt_common
-        /*
-        let (results, consumed) = Metadatum::decode_all(&buf[idx..idx + metadata_length]);
+        if idx + metadata_length > buf.len() {
+            return Err(bt_common::packet_encoding::Error::UnexpectedDataLength);
+        }
+        let (results, consumed) = Metadata::decode_all(&buf[idx..idx + metadata_length]);
         if consumed != metadata_length {
             return Err(bt_common::packet_encoding::Error::UnexpectedDataLength);
         }
-        let metadata = results.into_iter().filter(Result::ok).collect();
+        let metadata = results.into_iter().filter_map(Result::ok).collect();
         idx += consumed;
-        */
-        idx += metadata_length as usize;
 
-        Ok((Self { codec_id, codec_specific_capabilities, metadata: () }, idx))
+        Ok((Self { codec_id, codec_specific_capabilities, metadata }, idx))
     }
 }
 
@@ -352,7 +352,7 @@
         0x00, // Len of metadata
     ];
 
-    const MULTIPLE_PAC_COMPLEX: [u8; 35] = [
+    const MULTIPLE_PAC_COMPLEX: [u8; 29] = [
         0x02, // Num of records; 2
         0x05, // CodecID: codec MSBC,
         0x00, 0x00, 0x00, 0x00, // CodecID: company and specific id (zero)
@@ -362,9 +362,8 @@
         0x05, 0x04, // lt: Octets per codec frame
         0x11, 0x00, // Minimum: 9
         0x00, 0x10, // Maximum: 4096
-        0x0A, // Len of metadata: 10
-        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
-        0x0A, // Metadata (not parsed at this time)
+        0x04, // Len of metadata: 4
+        0x03, 0x01, 0x03, 0x00, // PreferredAudioContexts
         0xFF, // CodecId: Vendor specific
         0xE0, 0x00, // Google
         0x01, 0x10, // ID 4097
@@ -486,6 +485,16 @@
             ],
         );
 
+        let metadata = &first.metadata;
+
+        assert_eq!(metadata.len(), 1);
+
+        let Metadata::PreferredAudioContexts(p) = &metadata[0] else {
+            panic!("expected PreferredAudioContexts, got {:?}", metadata[0]);
+        };
+
+        assert_eq!(p.len(), 2);
+
         let second = &pac.capabilities[1];
         assert_eq!(
             second.codec_id,