[bt-common] Add parsing of 16-bit UUIDs

Test: updated tests; cargo test
Change-Id: I25a2168d70cbcb82aa057d4a8006dc016da7286a
Reviewed-on: https://bluetooth-review.git.corp.google.com/c/bluetooth/+/1380
Reviewed-by: Ani Ramakrishnan <aniramakri@google.com>
diff --git a/rust/bt-common/src/packet_encoding.rs b/rust/bt-common/src/packet_encoding.rs
index 10058b8..3667ee1 100644
--- a/rust/bt-common/src/packet_encoding.rs
+++ b/rust/bt-common/src/packet_encoding.rs
@@ -26,8 +26,8 @@
     fn encode(&self, buf: &mut [u8]) -> ::core::result::Result<(), Self::Error>;
 }
 
-/// Generates an enum value where each variant can be converted into a constant in the given
-/// raw_type.
+/// Generates an enum value where each variant can be converted into a constant
+/// in the given raw_type.
 ///
 /// For example:
 /// decodable_enum! {
@@ -126,4 +126,7 @@
 
     #[error("Unrecognized type for {0}: {1}")]
     UnrecognizedType(String, u8),
+
+    #[error("Uuid parsing error: {0}")]
+    Uuid(uuid::Error),
 }
diff --git a/rust/bt-common/src/uuids.rs b/rust/bt-common/src/uuids.rs
index bb7c0d0..f640805 100644
--- a/rust/bt-common/src/uuids.rs
+++ b/rust/bt-common/src/uuids.rs
@@ -72,10 +72,19 @@
 }
 
 impl core::str::FromStr for Uuid {
-    type Err = uuid::Error;
+    type Err = crate::packet_encoding::Error;
 
     fn from_str(s: &str) -> core::result::Result<Uuid, Self::Err> {
-        uuid::Uuid::parse_str(s).map(|uuid| Uuid(uuid))
+        if s.len() == 4 || s.len() == 6 {
+            return match u16::from_str_radix(&s[s.len() - 4..], 16) {
+                Ok(short) => Ok(Uuid::from_u16(short)),
+                Err(_) => Err(crate::packet_encoding::Error::InvalidParameter(s.to_owned())),
+            };
+        }
+        match uuid::Uuid::parse_str(s) {
+            Ok(uuid) => Ok(Uuid(uuid)),
+            Err(e) => Err(crate::packet_encoding::Error::Uuid(e)),
+        }
     }
 }
 
@@ -258,4 +267,17 @@
 
         assert_eq!(test_map.get(&Uuid::from_u16(0x1234)).unwrap().name, "Test 2");
     }
+
+    #[test]
+    fn parse() {
+        assert_eq!("1814".parse(), Ok(Uuid::from_u16(0x1814)));
+        assert_eq!("0x2a79".parse(), Ok(Uuid::from_u16(0x2a79)));
+        let unknown_long_uuid = "2686f39c-bada-4658-854a-a62e7e5e8b8d";
+        assert_eq!(
+            unknown_long_uuid.parse(),
+            Ok::<Uuid, crate::packet_encoding::Error>(
+                uuid::Uuid::parse_str(unknown_long_uuid).unwrap().into()
+            )
+        );
+    }
 }