bluetooth_traits/
scanfilter.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 std::collections::{HashMap, HashSet};
6use std::slice::Iter;
7
8use base::id::WebViewId;
9use serde::{Deserialize, Serialize};
10
11// A device name can never be longer than 29 bytes. An adv packet is at most
12// 31 bytes long. The length and identifier of the length field take 2 bytes.
13// That leaves 29 bytes for the name.
14const MAX_NAME_LENGTH: usize = 29;
15
16#[derive(Debug, Deserialize, Serialize)]
17pub struct ServiceUUIDSequence(Vec<String>);
18
19impl ServiceUUIDSequence {
20    pub fn new(vec: Vec<String>) -> ServiceUUIDSequence {
21        ServiceUUIDSequence(vec)
22    }
23
24    fn get_services_set(&self) -> HashSet<String> {
25        self.0.iter().map(String::clone).collect()
26    }
27}
28
29type ManufacturerData = HashMap<u16, (Vec<u8>, Vec<u8>)>;
30type ServiceData = HashMap<String, (Vec<u8>, Vec<u8>)>;
31
32#[derive(Debug, Deserialize, Serialize)]
33pub struct BluetoothScanfilter {
34    name: Option<String>,
35    name_prefix: String,
36    services: ServiceUUIDSequence,
37    manufacturer_data: Option<ManufacturerData>,
38    service_data: Option<ServiceData>,
39}
40
41impl BluetoothScanfilter {
42    pub fn new(
43        name: Option<String>,
44        name_prefix: String,
45        services: Vec<String>,
46        manufacturer_data: Option<ManufacturerData>,
47        service_data: Option<ServiceData>,
48    ) -> BluetoothScanfilter {
49        BluetoothScanfilter {
50            name,
51            name_prefix,
52            services: ServiceUUIDSequence::new(services),
53            manufacturer_data,
54            service_data,
55        }
56    }
57
58    pub fn get_name(&self) -> Option<&str> {
59        self.name.as_deref()
60    }
61
62    pub fn get_name_prefix(&self) -> &str {
63        &self.name_prefix
64    }
65
66    pub fn get_services(&self) -> &[String] {
67        &self.services.0
68    }
69
70    pub fn get_manufacturer_data(&self) -> Option<&ManufacturerData> {
71        self.manufacturer_data.as_ref()
72    }
73
74    pub fn get_service_data(&self) -> Option<&ServiceData> {
75        self.service_data.as_ref()
76    }
77
78    pub fn is_empty_or_invalid(&self) -> bool {
79        (self.name.is_none() &&
80            self.name_prefix.is_empty() &&
81            self.get_services().is_empty() &&
82            self.manufacturer_data.is_none() &&
83            self.service_data.is_none()) ||
84            self.get_name().unwrap_or("").len() > MAX_NAME_LENGTH ||
85            self.name_prefix.len() > MAX_NAME_LENGTH
86    }
87}
88
89#[derive(Debug, Deserialize, Serialize)]
90pub struct BluetoothScanfilterSequence(Vec<BluetoothScanfilter>);
91
92impl BluetoothScanfilterSequence {
93    pub fn new(vec: Vec<BluetoothScanfilter>) -> BluetoothScanfilterSequence {
94        BluetoothScanfilterSequence(vec)
95    }
96
97    pub fn has_empty_or_invalid_filter(&self) -> bool {
98        self.0.iter().any(BluetoothScanfilter::is_empty_or_invalid)
99    }
100
101    pub fn iter(&self) -> Iter<'_, BluetoothScanfilter> {
102        self.0.iter()
103    }
104
105    fn get_services_set(&self) -> HashSet<String> {
106        self.iter()
107            .flat_map(|filter| filter.services.get_services_set())
108            .collect()
109    }
110
111    fn is_empty(&self) -> bool {
112        self.0.is_empty()
113    }
114}
115
116#[derive(Debug, Deserialize, Serialize)]
117pub struct RequestDeviceoptions {
118    webview_id: WebViewId,
119    filters: BluetoothScanfilterSequence,
120    optional_services: ServiceUUIDSequence,
121}
122
123impl RequestDeviceoptions {
124    pub fn new(
125        webview_id: WebViewId,
126        filters: BluetoothScanfilterSequence,
127        services: ServiceUUIDSequence,
128    ) -> RequestDeviceoptions {
129        RequestDeviceoptions {
130            webview_id,
131            filters,
132            optional_services: services,
133        }
134    }
135
136    pub fn webview_id(&self) -> WebViewId {
137        self.webview_id
138    }
139
140    pub fn get_filters(&self) -> &BluetoothScanfilterSequence {
141        &self.filters
142    }
143
144    pub fn get_services_set(&self) -> HashSet<String> {
145        &self.filters.get_services_set() | &self.optional_services.get_services_set()
146    }
147
148    pub fn is_accepting_all_devices(&self) -> bool {
149        self.filters.is_empty()
150    }
151}