script/dom/bluetooth/
bluetoothuuid.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use regex::Regex;
7
8use crate::dom::bindings::codegen::Bindings::BluetoothUUIDBinding::BluetoothUUIDMethods;
9use crate::dom::bindings::codegen::UnionTypes::StringOrUnsignedLong;
10use crate::dom::bindings::error::Error::Type;
11use crate::dom::bindings::error::Fallible;
12use crate::dom::bindings::reflector::Reflector;
13use crate::dom::bindings::str::DOMString;
14use crate::dom::window::Window;
15
16#[allow(clippy::upper_case_acronyms)]
17pub(crate) type UUID = DOMString;
18pub(crate) type BluetoothServiceUUID = StringOrUnsignedLong;
19pub(crate) type BluetoothCharacteristicUUID = StringOrUnsignedLong;
20pub(crate) type BluetoothDescriptorUUID = StringOrUnsignedLong;
21
22// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
23#[dom_struct]
24pub(crate) struct BluetoothUUID {
25    reflector_: Reflector,
26}
27
28// https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
29const BLUETOOTH_ASSIGNED_SERVICES: &[(&str, u32)] = &[
30    ("org.bluetooth.service.alert_notification", 0x1811_u32),
31    ("org.bluetooth.service.automation_io", 0x1815_u32),
32    ("org.bluetooth.service.battery_service", 0x180f_u32),
33    ("org.bluetooth.service.blood_pressure", 0x1810_u32),
34    ("org.bluetooth.service.body_composition", 0x181b_u32),
35    ("org.bluetooth.service.bond_management", 0x181e_u32),
36    (
37        "org.bluetooth.service.continuous_glucose_monitoring",
38        0x181f_u32,
39    ),
40    ("org.bluetooth.service.current_time", 0x1805_u32),
41    ("org.bluetooth.service.cycling_power", 0x1818_u32),
42    (
43        "org.bluetooth.service.cycling_speed_and_cadence",
44        0x1816_u32,
45    ),
46    ("org.bluetooth.service.device_information", 0x180a_u32),
47    ("org.bluetooth.service.environmental_sensing", 0x181a_u32),
48    ("org.bluetooth.service.generic_access", 0x1800_u32),
49    ("org.bluetooth.service.generic_attribute", 0x1801_u32),
50    ("org.bluetooth.service.glucose", 0x1808_u32),
51    ("org.bluetooth.service.health_thermometer", 0x1809_u32),
52    ("org.bluetooth.service.heart_rate", 0x180d_u32),
53    ("org.bluetooth.service.http_proxy", 0x1823_u32),
54    ("org.bluetooth.service.human_interface_device", 0x1812_u32),
55    ("org.bluetooth.service.immediate_alert", 0x1802_u32),
56    ("org.bluetooth.service.indoor_positioning", 0x1821_u32),
57    (
58        "org.bluetooth.service.internet_protocol_support",
59        0x1820_u32,
60    ),
61    ("org.bluetooth.service.link_loss", 0x1803_u32),
62    ("org.bluetooth.service.location_and_navigation", 0x1819_u32),
63    ("org.bluetooth.service.next_dst_change", 0x1807_u32),
64    ("org.bluetooth.service.object_transfer", 0x1825_u32),
65    ("org.bluetooth.service.phone_alert_status", 0x180e_u32),
66    ("org.bluetooth.service.pulse_oximeter", 0x1822_u32),
67    ("org.bluetooth.service.reference_time_update", 0x1806_u32),
68    (
69        "org.bluetooth.service.running_speed_and_cadence",
70        0x1814_u32,
71    ),
72    ("org.bluetooth.service.scan_parameters", 0x1813_u32),
73    ("org.bluetooth.service.transport_discovery", 0x1824),
74    ("org.bluetooth.service.tx_power", 0x1804_u32),
75    ("org.bluetooth.service.user_data", 0x181c_u32),
76    ("org.bluetooth.service.weight_scale", 0x181d_u32),
77];
78
79// https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
80const BLUETOOTH_ASSIGNED_CHARCTERISTICS: &[(&str, u32)] = &[
81    (
82        "org.bluetooth.characteristic.aerobic_heart_rate_lower_limit",
83        0x2a7e_u32,
84    ),
85    (
86        "org.bluetooth.characteristic.aerobic_heart_rate_upper_limit",
87        0x2a84_u32,
88    ),
89    ("org.bluetooth.characteristic.aerobic_threshold", 0x2a7f_u32),
90    ("org.bluetooth.characteristic.age", 0x2a80_u32),
91    ("org.bluetooth.characteristic.aggregate", 0x2a5a_u32),
92    ("org.bluetooth.characteristic.alert_category_id", 0x2a43_u32),
93    (
94        "org.bluetooth.characteristic.alert_category_id_bit_mask",
95        0x2a42_u32,
96    ),
97    ("org.bluetooth.characteristic.alert_level", 0x2a06_u32),
98    (
99        "org.bluetooth.characteristic.alert_notification_control_point",
100        0x2a44_u32,
101    ),
102    ("org.bluetooth.characteristic.alert_status", 0x2a3f_u32),
103    ("org.bluetooth.characteristic.altitude", 0x2ab3_u32),
104    (
105        "org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit",
106        0x2a81_u32,
107    ),
108    (
109        "org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit",
110        0x2a82_u32,
111    ),
112    (
113        "org.bluetooth.characteristic.anaerobic_threshold",
114        0x2a83_u32,
115    ),
116    ("org.bluetooth.characteristic.analog", 0x2a58_u32),
117    (
118        "org.bluetooth.characteristic.apparent_wind_direction",
119        0x2a73_u32,
120    ),
121    (
122        "org.bluetooth.characteristic.apparent_wind_speed",
123        0x2a72_u32,
124    ),
125    ("org.bluetooth.characteristic.gap.appearance", 0x2a01_u32),
126    (
127        "org.bluetooth.characteristic.barometric_pressure_trend",
128        0x2aa3_u32,
129    ),
130    ("org.bluetooth.characteristic.battery_level", 0x2a19_u32),
131    (
132        "org.bluetooth.characteristic.blood_pressure_feature",
133        0x2a49_u32,
134    ),
135    (
136        "org.bluetooth.characteristic.blood_pressure_measurement",
137        0x2a35_u32,
138    ),
139    (
140        "org.bluetooth.characteristic.body_composition_feature",
141        0x2a9b_u32,
142    ),
143    (
144        "org.bluetooth.characteristic.body_composition_measurement",
145        0x2a9c_u32,
146    ),
147    (
148        "org.bluetooth.characteristic.body_sensor_location",
149        0x2a38_u32,
150    ),
151    (
152        "org.bluetooth.characteristic.bond_management_control_point",
153        0x2aa4_u32,
154    ),
155    (
156        "org.bluetooth.characteristic.bond_management_feature",
157        0x2aa5_u32,
158    ),
159    (
160        "org.bluetooth.characteristic.boot_keyboard_input_report",
161        0x2a22_u32,
162    ),
163    (
164        "org.bluetooth.characteristic.boot_keyboard_output_report",
165        0x2a32_u32,
166    ),
167    (
168        "org.bluetooth.characteristic.boot_mouse_input_report",
169        0x2a33_u32,
170    ),
171    (
172        "org.bluetooth.characteristic.gap.central_address_resolution_support",
173        0x2aa6_u32,
174    ),
175    ("org.bluetooth.characteristic.cgm_feature", 0x2aa8_u32),
176    ("org.bluetooth.characteristic.cgm_measurement", 0x2aa7_u32),
177    (
178        "org.bluetooth.characteristic.cgm_session_run_time",
179        0x2aab_u32,
180    ),
181    (
182        "org.bluetooth.characteristic.cgm_session_start_time",
183        0x2aaa_u32,
184    ),
185    (
186        "org.bluetooth.characteristic.cgm_specific_ops_control_point",
187        0x2aac_u32,
188    ),
189    ("org.bluetooth.characteristic.cgm_status", 0x2aa9_u32),
190    ("org.bluetooth.characteristic.csc_feature", 0x2a5c_u32),
191    ("org.bluetooth.characteristic.csc_measurement", 0x2a5b_u32),
192    ("org.bluetooth.characteristic.current_time", 0x2a2b_u32),
193    (
194        "org.bluetooth.characteristic.cycling_power_control_point",
195        0x2a66_u32,
196    ),
197    (
198        "org.bluetooth.characteristic.cycling_power_feature",
199        0x2a65_u32,
200    ),
201    (
202        "org.bluetooth.characteristic.cycling_power_measurement",
203        0x2a63_u32,
204    ),
205    (
206        "org.bluetooth.characteristic.cycling_power_vector",
207        0x2a64_u32,
208    ),
209    (
210        "org.bluetooth.characteristic.database_change_increment",
211        0x2a99_u32,
212    ),
213    ("org.bluetooth.characteristic.date_of_birth", 0x2a85_u32),
214    (
215        "org.bluetooth.characteristic.date_of_threshold_assessment",
216        0x2a86_u32,
217    ),
218    ("org.bluetooth.characteristic.date_time", 0x2a08_u32),
219    ("org.bluetooth.characteristic.day_date_time", 0x2a0a_u32),
220    ("org.bluetooth.characteristic.day_of_week", 0x2a09_u32),
221    (
222        "org.bluetooth.characteristic.descriptor_value_changed",
223        0x2a7d_u32,
224    ),
225    ("org.bluetooth.characteristic.gap.device_name", 0x2a00_u32),
226    ("org.bluetooth.characteristic.dew_point", 0x2a7b_u32),
227    ("org.bluetooth.characteristic.digital", 0x2a56_u32),
228    ("org.bluetooth.characteristic.dst_offset", 0x2a0d_u32),
229    ("org.bluetooth.characteristic.elevation", 0x2a6c_u32),
230    ("org.bluetooth.characteristic.email_address", 0x2a87_u32),
231    ("org.bluetooth.characteristic.exact_time_256", 0x2a0c_u32),
232    (
233        "org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit",
234        0x2a88_u32,
235    ),
236    (
237        "org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit",
238        0x2a89_u32,
239    ),
240    (
241        "org.bluetooth.characteristic.firmware_revision_string",
242        0x2a26_u32,
243    ),
244    ("org.bluetooth.characteristic.first_name", 0x2a8a_u32),
245    (
246        "org.bluetooth.characteristic.five_zone_heart_rate_limits",
247        0x2a8b_u32,
248    ),
249    ("org.bluetooth.characteristic.floor_number", 0x2ab2_u32),
250    ("org.bluetooth.characteristic.gender", 0x2a8c_u32),
251    ("org.bluetooth.characteristic.glucose_feature", 0x2a51_u32),
252    (
253        "org.bluetooth.characteristic.glucose_measurement",
254        0x2a18_u32,
255    ),
256    (
257        "org.bluetooth.characteristic.glucose_measurement_context",
258        0x2a34_u32,
259    ),
260    ("org.bluetooth.characteristic.gust_factor", 0x2a74_u32),
261    (
262        "org.bluetooth.characteristic.hardware_revision_string",
263        0x2a27_u32,
264    ),
265    (
266        "org.bluetooth.characteristic.heart_rate_control_point",
267        0x2a39_u32,
268    ),
269    ("org.bluetooth.characteristic.heart_rate_max", 0x2a8d_u32),
270    (
271        "org.bluetooth.characteristic.heart_rate_measurement",
272        0x2a37_u32,
273    ),
274    ("org.bluetooth.characteristic.heat_index", 0x2a7a_u32),
275    ("org.bluetooth.characteristic.height", 0x2a8e_u32),
276    ("org.bluetooth.characteristic.hid_control_point", 0x2a4c_u32),
277    ("org.bluetooth.characteristic.hid_information", 0x2a4a_u32),
278    ("org.bluetooth.characteristic.hip_circumference", 0x2a8f_u32),
279    (
280        "org.bluetooth.characteristic.http_control_point",
281        0x2aba_u32,
282    ),
283    ("org.bluetooth.characteristic.http_entity_body", 0x2ab9_u32),
284    ("org.bluetooth.characteristic.http_headers", 0x2ab7_u32),
285    ("org.bluetooth.characteristic.http_status_code", 0x2ab8_u32),
286    ("org.bluetooth.characteristic.https_security", 0x2abb_u32),
287    ("org.bluetooth.characteristic.humidity", 0x2a6f_u32),
288    (
289        "org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list",
290        0x2a2a_u32,
291    ),
292    (
293        "org.bluetooth.characteristic.indoor_positioning_configuration",
294        0x2aad_u32,
295    ),
296    (
297        "org.bluetooth.characteristic.intermediate_cuff_pressure",
298        0x2a36_u32,
299    ),
300    (
301        "org.bluetooth.characteristic.intermediate_temperature",
302        0x2a1e_u32,
303    ),
304    ("org.bluetooth.characteristic.irradiance", 0x2a77_u32),
305    ("org.bluetooth.characteristic.language", 0x2aa2_u32),
306    ("org.bluetooth.characteristic.last_name", 0x2a90_u32),
307    ("org.bluetooth.characteristic.latitude", 0x2aae_u32),
308    ("org.bluetooth.characteristic.ln_control_point", 0x2a6b_u32),
309    ("org.bluetooth.characteristic.ln_feature", 0x2a6a_u32),
310    (
311        "org.bluetooth.characteristic.local_east_coordinate.xml",
312        0x2ab1_u32,
313    ),
314    (
315        "org.bluetooth.characteristic.local_north_coordinate",
316        0x2ab0_u32,
317    ),
318    (
319        "org.bluetooth.characteristic.local_time_information",
320        0x2a0f_u32,
321    ),
322    (
323        "org.bluetooth.characteristic.location_and_speed",
324        0x2a67_u32,
325    ),
326    ("org.bluetooth.characteristic.location_name", 0x2ab5_u32),
327    ("org.bluetooth.characteristic.longitude", 0x2aaf_u32),
328    (
329        "org.bluetooth.characteristic.magnetic_declination",
330        0x2a2c_u32,
331    ),
332    (
333        "org.bluetooth.characteristic.magnetic_flux_density_2d",
334        0x2aa0_u32,
335    ),
336    (
337        "org.bluetooth.characteristic.magnetic_flux_density_3d",
338        0x2aa1_u32,
339    ),
340    (
341        "org.bluetooth.characteristic.manufacturer_name_string",
342        0x2a29_u32,
343    ),
344    (
345        "org.bluetooth.characteristic.maximum_recommended_heart_rate",
346        0x2a91_u32,
347    ),
348    (
349        "org.bluetooth.characteristic.measurement_interval",
350        0x2a21_u32,
351    ),
352    (
353        "org.bluetooth.characteristic.model_number_string",
354        0x2a24_u32,
355    ),
356    ("org.bluetooth.characteristic.navigation", 0x2a68_u32),
357    ("org.bluetooth.characteristic.new_alert", 0x2a46_u32),
358    (
359        "org.bluetooth.characteristic.object_action_control_point",
360        0x2ac5_u32,
361    ),
362    ("org.bluetooth.characteristic.object_changed", 0x2ac8_u32),
363    (
364        "org.bluetooth.characteristic.object_first_created",
365        0x2ac1_u32,
366    ),
367    ("org.bluetooth.characteristic.object_id", 0x2ac3_u32),
368    (
369        "org.bluetooth.characteristic.object_last_modified",
370        0x2ac2_u32,
371    ),
372    (
373        "org.bluetooth.characteristic.object_list_control_point",
374        0x2ac6_u32,
375    ),
376    (
377        "org.bluetooth.characteristic.object_list_filter",
378        0x2ac7_u32,
379    ),
380    ("org.bluetooth.characteristic.object_name", 0x2abe_u32),
381    ("org.bluetooth.characteristic.object_properties", 0x2ac4_u32),
382    ("org.bluetooth.characteristic.object_size", 0x2ac0_u32),
383    ("org.bluetooth.characteristic.object_type", 0x2abf_u32),
384    ("org.bluetooth.characteristic.ots_feature", 0x2abd_u32),
385    (
386        "org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters",
387        0x2a04_u32,
388    ),
389    (
390        "org.bluetooth.characteristic.gap.peripheral_privacy_flag",
391        0x2a02_u32,
392    ),
393    (
394        "org.bluetooth.characteristic.plx_continuous_measurement",
395        0x2a5f_u32,
396    ),
397    ("org.bluetooth.characteristic.plx_features", 0x2a60_u32),
398    (
399        "org.bluetooth.characteristic.plx_spot_check_measurement",
400        0x2a5e_u32,
401    ),
402    ("org.bluetooth.characteristic.pnp_id", 0x2a50_u32),
403    (
404        "org.bluetooth.characteristic.pollen_concentration",
405        0x2a75_u32,
406    ),
407    ("org.bluetooth.characteristic.position_quality", 0x2a69_u32),
408    ("org.bluetooth.characteristic.pressure", 0x2a6d_u32),
409    ("org.bluetooth.characteristic.protocol_mode", 0x2a4e_u32),
410    ("org.bluetooth.characteristic.rainfall", 0x2a78_u32),
411    (
412        "org.bluetooth.characteristic.gap.reconnection_address",
413        0x2a03_u32,
414    ),
415    (
416        "org.bluetooth.characteristic.record_access_control_point",
417        0x2a52_u32,
418    ),
419    (
420        "org.bluetooth.characteristic.reference_time_information",
421        0x2a14_u32,
422    ),
423    ("org.bluetooth.characteristic.report", 0x2a4d_u32),
424    ("org.bluetooth.characteristic.report_map", 0x2a4b_u32),
425    (
426        "org.bluetooth.characteristic.resting_heart_rate",
427        0x2a92_u32,
428    ),
429    (
430        "org.bluetooth.characteristic.ringer_control_point",
431        0x2a40_u32,
432    ),
433    ("org.bluetooth.characteristic.ringer_setting", 0x2a41_u32),
434    ("org.bluetooth.characteristic.rsc_feature", 0x2a54_u32),
435    ("org.bluetooth.characteristic.rsc_measurement", 0x2a53_u32),
436    ("org.bluetooth.characteristic.sc_control_point", 0x2a55_u32),
437    (
438        "org.bluetooth.characteristic.scan_interval_window",
439        0x2a4f_u32,
440    ),
441    ("org.bluetooth.characteristic.scan_refresh", 0x2a31_u32),
442    ("org.bluetooth.characteristic.sensor_location", 0x2a5d_u32),
443    (
444        "org.bluetooth.characteristic.serial_number_string",
445        0x2a25_u32,
446    ),
447    (
448        "org.bluetooth.characteristic.gatt.service_changed",
449        0x2a05_u32,
450    ),
451    (
452        "org.bluetooth.characteristic.software_revision_string",
453        0x2a28_u32,
454    ),
455    (
456        "org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds",
457        0x2a93_u32,
458    ),
459    (
460        "org.bluetooth.characteristic.supported_new_alert_category",
461        0x2a47_u32,
462    ),
463    (
464        "org.bluetooth.characteristic.supported_unread_alert_category",
465        0x2a48_u32,
466    ),
467    ("org.bluetooth.characteristic.system_id", 0x2a23_u32),
468    ("org.bluetooth.characteristic.tds_control_point", 0x2abc_u32),
469    ("org.bluetooth.characteristic.temperature", 0x2a6e_u32),
470    (
471        "org.bluetooth.characteristic.temperature_measurement",
472        0x2a1c_u32,
473    ),
474    ("org.bluetooth.characteristic.temperature_type", 0x2a1d_u32),
475    (
476        "org.bluetooth.characteristic.three_zone_heart_rate_limits",
477        0x2a94_u32,
478    ),
479    ("org.bluetooth.characteristic.time_accuracy", 0x2a12_u32),
480    ("org.bluetooth.characteristic.time_source", 0x2a13_u32),
481    (
482        "org.bluetooth.characteristic.time_update_control_point",
483        0x2a16_u32,
484    ),
485    ("org.bluetooth.characteristic.time_update_state", 0x2a17_u32),
486    ("org.bluetooth.characteristic.time_with_dst", 0x2a11_u32),
487    ("org.bluetooth.characteristic.time_zone", 0x2a0e_u32),
488    (
489        "org.bluetooth.characteristic.true_wind_direction",
490        0x2a71_u32,
491    ),
492    ("org.bluetooth.characteristic.true_wind_speed", 0x2a70_u32),
493    (
494        "org.bluetooth.characteristic.two_zone_heart_rate_limit",
495        0x2a95_u32,
496    ),
497    ("org.bluetooth.characteristic.tx_power_level", 0x2a07_u32),
498    ("org.bluetooth.characteristic.uncertainty", 0x2ab4_u32),
499    (
500        "org.bluetooth.characteristic.unread_alert_status",
501        0x2a45_u32,
502    ),
503    ("org.bluetooth.characteristic.uri", 0x2ab6_u32),
504    (
505        "org.bluetooth.characteristic.user_control_point",
506        0x2a9f_u32,
507    ),
508    ("org.bluetooth.characteristic.user_index", 0x2a9a_u32),
509    ("org.bluetooth.characteristic.uv_index", 0x2a76_u32),
510    ("org.bluetooth.characteristic.vo2_max", 0x2a96_u32),
511    (
512        "org.bluetooth.characteristic.waist_circumference",
513        0x2a97_u32,
514    ),
515    ("org.bluetooth.characteristic.weight", 0x2a98_u32),
516    (
517        "org.bluetooth.characteristic.weight_measurement",
518        0x2a9d_u32,
519    ),
520    (
521        "org.bluetooth.characteristic.weight_scale_feature",
522        0x2a9e_u32,
523    ),
524    ("org.bluetooth.characteristic.wind_chill", 0x2a79_u32),
525];
526
527// https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
528const BLUETOOTH_ASSIGNED_DESCRIPTORS: &[(&str, u32)] = &[
529    (
530        "org.bluetooth.descriptor.gatt.characteristic_extended_properties",
531        0x2900_u32,
532    ),
533    (
534        "org.bluetooth.descriptor.gatt.characteristic_user_description",
535        0x2901_u32,
536    ),
537    (
538        "org.bluetooth.descriptor.gatt.client_characteristic_configuration",
539        0x2902_u32,
540    ),
541    (
542        "org.bluetooth.descriptor.gatt.server_characteristic_configuration",
543        0x2903_u32,
544    ),
545    (
546        "org.bluetooth.descriptor.gatt.characteristic_presentation_format",
547        0x2904_u32,
548    ),
549    (
550        "org.bluetooth.descriptor.gatt.characteristic_aggregate_format",
551        0x2905_u32,
552    ),
553    ("org.bluetooth.descriptor.valid_range", 0x2906_u32),
554    (
555        "org.bluetooth.descriptor.external_report_reference",
556        0x2907_u32,
557    ),
558    ("org.bluetooth.descriptor.report_reference", 0x2908_u32),
559    ("org.bluetooth.descriptor.number_of_digitals", 0x2909_u32),
560    ("org.bluetooth.descriptor.value_trigger_setting", 0x290a_u32),
561    ("org.bluetooth.descriptor.es_configuration", 0x290b_u32),
562    ("org.bluetooth.descriptor.es_measurement", 0x290c_u32),
563    ("org.bluetooth.descriptor.es_trigger_setting", 0x290d_u32),
564    ("org.bluetooth.descriptor.time_trigger_setting", 0x290e_u32),
565];
566
567const BASE_UUID: &str = "-0000-1000-8000-00805f9b34fb";
568const SERVICE_PREFIX: &str = "org.bluetooth.service";
569const CHARACTERISTIC_PREFIX: &str = "org.bluetooth.characteristic";
570const DESCRIPTOR_PREFIX: &str = "org.bluetooth.descriptor";
571const VALID_UUID_REGEX: &str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
572// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=314
573const UUID_ERROR_MESSAGE: &str = "It must be a valid UUID alias (e.g. 0x1234), \
574    UUID (lowercase hex characters e.g. '00001234-0000-1000-8000-00805f9b34fb'),\nor recognized standard name from";
575// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=321
576const SERVICES_ERROR_MESSAGE: &str = "https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx\
577     \ne.g. 'alert_notification'.";
578// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=327
579const CHARACTERISTIC_ERROR_MESSAGE: &str = "https://developer.bluetooth.org/gatt/characteristics/Pages/\
580     CharacteristicsHome.aspx\ne.g. 'aerobic_heart_rate_lower_limit'.";
581// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=333
582const DESCRIPTOR_ERROR_MESSAGE: &str = "https://developer.bluetooth.org/gatt/descriptors/Pages/\
583     DescriptorsHomePage.aspx\ne.g. 'gatt.characteristic_presentation_format'.";
584
585impl BluetoothUUIDMethods<crate::DomTypeHolder> for BluetoothUUID {
586    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-canonicaluuid
587    fn CanonicalUUID(_: &Window, alias: u32) -> UUID {
588        canonical_uuid(alias)
589    }
590
591    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice
592    fn GetService(_: &Window, name: BluetoothServiceUUID) -> Fallible<UUID> {
593        Self::service(name)
594    }
595
596    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getcharacteristic
597    fn GetCharacteristic(_: &Window, name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
598        Self::characteristic(name)
599    }
600
601    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getdescriptor
602    fn GetDescriptor(_: &Window, name: BluetoothDescriptorUUID) -> Fallible<UUID> {
603        Self::descriptor(name)
604    }
605}
606
607impl BluetoothUUID {
608    pub(crate) fn service(name: BluetoothServiceUUID) -> Fallible<UUID> {
609        resolve_uuid_name(name, BLUETOOTH_ASSIGNED_SERVICES, SERVICE_PREFIX)
610    }
611
612    pub(crate) fn characteristic(name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
613        resolve_uuid_name(
614            name,
615            BLUETOOTH_ASSIGNED_CHARCTERISTICS,
616            CHARACTERISTIC_PREFIX,
617        )
618    }
619
620    pub(crate) fn descriptor(name: BluetoothDescriptorUUID) -> Fallible<UUID> {
621        resolve_uuid_name(name, BLUETOOTH_ASSIGNED_DESCRIPTORS, DESCRIPTOR_PREFIX)
622    }
623}
624
625fn canonical_uuid(alias: u32) -> UUID {
626    UUID::from(format!("{:08x}", &alias) + BASE_UUID)
627}
628
629// https://webbluetoothcg.github.io/web-bluetooth/#resolveuuidname
630fn resolve_uuid_name(
631    name: StringOrUnsignedLong,
632    assigned_numbers_table: &'static [(&'static str, u32)],
633    prefix: &str,
634) -> Fallible<DOMString> {
635    match name {
636        // Step 1.
637        StringOrUnsignedLong::UnsignedLong(unsigned32) => Ok(canonical_uuid(unsigned32)),
638        StringOrUnsignedLong::String(dstring) => {
639            // Step 2.
640            let regex = Regex::new(VALID_UUID_REGEX).unwrap();
641            if regex.is_match(&dstring) {
642                Ok(dstring)
643            } else {
644                // Step 3.
645                let concatenated = format!("{}.{}", prefix, dstring);
646                let is_in_table = assigned_numbers_table.iter().find(|p| p.0 == concatenated);
647                match is_in_table {
648                    Some(&(_, alias)) => Ok(canonical_uuid(alias)),
649                    None => {
650                        let (attribute_type, error_url_message) = match prefix {
651                            SERVICE_PREFIX => ("Service", SERVICES_ERROR_MESSAGE),
652                            CHARACTERISTIC_PREFIX => {
653                                ("Characteristic", CHARACTERISTIC_ERROR_MESSAGE)
654                            },
655                            DESCRIPTOR_PREFIX => ("Descriptor", DESCRIPTOR_ERROR_MESSAGE),
656                            _ => unreachable!(),
657                        };
658                        // Step 4.
659                        Err(Type(format!(
660                            "Invalid {} name : '{}'.\n{} {}",
661                            attribute_type, dstring, UUID_ERROR_MESSAGE, error_url_message
662                        )))
663                    },
664                }
665            }
666        },
667    }
668}