fuchsia_bluetooth/
assigned_numbers.rs1use self::constants::{
6 CHARACTERISTIC_NUMBERS, CUSTOM_SERVICE_UUIDS, DESCRIPTOR_NUMBERS, SERVICE_UUIDS,
7};
8use crate::types::Uuid;
9
10pub(crate) mod constants;
11pub mod ltv;
12
13#[derive(Clone, Copy, Debug, PartialEq)]
16pub struct AssignedNumber {
17 pub number: u16,
19 pub abbreviation: Option<&'static str>,
21 pub name: &'static str,
23}
24
25impl AssignedNumber {
26 pub fn matches(&self, identifier: &str) -> bool {
31 let identifier = &identifier.to_uppercase();
32 self.matches_abbreviation(identifier)
33 || self.matches_name(identifier)
34 || self.matches_number(identifier)
35 }
36
37 fn matches_abbreviation(&self, identifier: &str) -> bool {
38 self.abbreviation.map(|abbr| abbr == identifier).unwrap_or(false)
39 }
40
41 fn matches_name(&self, identifier: &str) -> bool {
42 self.name.to_uppercase() == identifier
43 }
44
45 fn matches_number(&self, identifier: &str) -> bool {
48 let identifier = if identifier.starts_with("0X") { &identifier[2..] } else { identifier };
49 let string = Uuid::new16(self.number).to_string().to_uppercase();
50 if identifier.len() == 32 + 4 {
51 identifier == string
52 } else {
53 let short_form =
54 string.split("-").next().expect("split iter always has at least 1 item");
55 short_form == format!("{:0>8}", identifier)
57 }
58 }
59}
60
61pub fn find_service_uuid(identifier: &str) -> Option<AssignedNumber> {
65 SERVICE_UUIDS
66 .iter()
67 .chain(CUSTOM_SERVICE_UUIDS.iter())
68 .find(|sn| sn.matches(identifier))
69 .copied()
70}
71
72pub fn find_characteristic_number(identifier: &str) -> Option<AssignedNumber> {
76 CHARACTERISTIC_NUMBERS.iter().find(|cn| cn.matches(identifier)).map(|&an| an)
77}
78
79pub fn find_descriptor_number(identifier: &str) -> Option<AssignedNumber> {
83 DESCRIPTOR_NUMBERS.iter().find(|dn| dn.matches(identifier)).map(|&an| an)
84}
85
86#[macro_export]
87macro_rules! assigned_number {
88 ($num:expr, $abbr:expr, $name:expr) => {
89 AssignedNumber { number: $num, abbreviation: Some($abbr), name: $name }
90 };
91 ($num:expr, $name:expr) => {
92 AssignedNumber { number: $num, abbreviation: None, name: $name }
93 };
94}
95
96#[cfg(test)]
97mod tests {
98 use super::{
99 find_characteristic_number, find_descriptor_number, find_service_uuid,
100 CHARACTERISTIC_NUMBERS, CUSTOM_SERVICE_UUIDS, DESCRIPTOR_NUMBERS, SERVICE_UUIDS,
101 };
102
103 #[test]
104 fn test_find_characteristic_number() {
105 assert_eq!(find_characteristic_number("Device Name"), Some(CHARACTERISTIC_NUMBERS[0]));
106 assert_eq!(find_characteristic_number("aPPEARANCE"), Some(CHARACTERISTIC_NUMBERS[1]));
107 assert_eq!(find_characteristic_number("fake characteristic name"), None);
108 assert_eq!(find_characteristic_number("2a00"), Some(CHARACTERISTIC_NUMBERS[0]));
109 assert_eq!(find_characteristic_number("zzzz"), None);
110 }
111
112 #[test]
113 fn test_find_descriptor_number() {
114 assert_eq!(find_descriptor_number("Report reference"), Some(DESCRIPTOR_NUMBERS[8]));
115 assert_eq!(find_descriptor_number("fake descriptor name"), None);
116 assert_eq!(
117 find_descriptor_number("00002908-0000-1000-8000-00805F9B34FB"),
118 Some(DESCRIPTOR_NUMBERS[8])
119 );
120 assert_eq!(find_descriptor_number("2908"), Some(DESCRIPTOR_NUMBERS[8]));
121 assert_eq!(find_descriptor_number("zzzz"), None);
122 }
123
124 #[test]
125 fn test_find_service_uuid() {
126 assert_eq!(find_service_uuid("GAP"), Some(SERVICE_UUIDS[0]));
127 assert_eq!(find_service_uuid("Gap"), Some(SERVICE_UUIDS[0]));
128 assert_eq!(find_service_uuid("gap"), Some(SERVICE_UUIDS[0]));
129 assert_eq!(find_service_uuid("hIdS"), Some(SERVICE_UUIDS[16]));
130 assert_eq!(find_service_uuid("XYZ"), None);
131 assert_eq!(find_service_uuid("Human Interface Device Service"), Some(SERVICE_UUIDS[16]));
132 assert_eq!(find_service_uuid("Fake Service Name"), None);
133 assert_eq!(find_service_uuid("183A"), Some(SERVICE_UUIDS[39]));
134 assert_eq!(find_service_uuid("0x183a"), Some(SERVICE_UUIDS[39]));
135 assert_eq!(find_service_uuid("0000183a"), Some(SERVICE_UUIDS[39]));
136 assert_eq!(
137 find_service_uuid("0000183A-0000-1000-8000-00805F9B34FB"),
138 Some(SERVICE_UUIDS[39])
139 );
140 assert_eq!(
141 find_service_uuid("0000183a-0000-1000-8000-00805f9b34fb"),
142 Some(SERVICE_UUIDS[39])
143 );
144 assert_eq!(find_service_uuid("0000183A-0000-1000-8000-000000000000"), None);
145 assert_eq!(find_service_uuid("ZZZZZZZZ"), None);
146 assert_eq!(find_service_uuid("ZZZZZZZZ-0000-1000-8000-00805F9B34FB"), None);
147 assert_eq!(find_service_uuid("fdcf"), Some(CUSTOM_SERVICE_UUIDS[0]));
149 assert_eq!(find_service_uuid("FDE2"), Some(CUSTOM_SERVICE_UUIDS[19]));
150 }
151}