• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Core types
16 
17 use crate::adv::CommonDataTypeCode;
18 use lazy_static::lazy_static;
19 use nom::{bytes, combinator};
20 use pyo3::{intern, PyObject, PyResult, Python};
21 use std::fmt;
22 
23 lazy_static! {
24     static ref BASE_UUID: [u8; 16] = hex::decode("0000000000001000800000805F9B34FB")
25         .unwrap()
26         .try_into()
27         .unwrap();
28 }
29 
30 /// A type code and data pair from an advertisement
31 pub type AdvertisementDataUnit = (CommonDataTypeCode, Vec<u8>);
32 
33 /// Contents of an advertisement
34 pub struct AdvertisingData(pub(crate) PyObject);
35 
36 impl AdvertisingData {
37     /// Data units in the advertisement contents
data_units(&self) -> PyResult<Vec<AdvertisementDataUnit>>38     pub fn data_units(&self) -> PyResult<Vec<AdvertisementDataUnit>> {
39         Python::with_gil(|py| {
40             let list = self.0.getattr(py, intern!(py, "ad_structures"))?;
41 
42             list.as_ref(py)
43                 .iter()?
44                 .collect::<Result<Vec<_>, _>>()?
45                 .into_iter()
46                 .map(|tuple| {
47                     let type_code = tuple
48                         .call_method1(intern!(py, "__getitem__"), (0,))?
49                         .extract::<u8>()?
50                         .into();
51                     let data = tuple
52                         .call_method1(intern!(py, "__getitem__"), (1,))?
53                         .extract::<Vec<u8>>()?;
54                     Ok((type_code, data))
55                 })
56                 .collect::<Result<Vec<_>, _>>()
57         })
58     }
59 }
60 
61 /// 16-bit UUID
62 #[derive(PartialEq, Eq, Hash, Clone, Copy)]
63 pub struct Uuid16 {
64     /// Big-endian bytes
65     uuid: [u8; 2],
66 }
67 
68 impl Uuid16 {
69     /// Construct a UUID from little-endian bytes
from_le_bytes(mut bytes: [u8; 2]) -> Self70     pub fn from_le_bytes(mut bytes: [u8; 2]) -> Self {
71         bytes.reverse();
72         Self::from_be_bytes(bytes)
73     }
74 
75     /// Construct a UUID from big-endian bytes
from_be_bytes(bytes: [u8; 2]) -> Self76     pub fn from_be_bytes(bytes: [u8; 2]) -> Self {
77         Self { uuid: bytes }
78     }
79 
80     /// The UUID in big-endian bytes form
as_be_bytes(&self) -> [u8; 2]81     pub fn as_be_bytes(&self) -> [u8; 2] {
82         self.uuid
83     }
84 
85     /// The UUID in little-endian bytes form
as_le_bytes(&self) -> [u8; 2]86     pub fn as_le_bytes(&self) -> [u8; 2] {
87         let mut uuid = self.uuid;
88         uuid.reverse();
89         uuid
90     }
91 
parse_le(input: &[u8]) -> nom::IResult<&[u8], Self>92     pub(crate) fn parse_le(input: &[u8]) -> nom::IResult<&[u8], Self> {
93         combinator::map_res(bytes::complete::take(2_usize), |b: &[u8]| {
94             b.try_into().map(|mut uuid: [u8; 2]| {
95                 uuid.reverse();
96                 Self { uuid }
97             })
98         })(input)
99     }
100 }
101 
102 impl fmt::Debug for Uuid16 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result103     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104         write!(f, "UUID-16:{}", hex::encode_upper(self.uuid))
105     }
106 }
107 
108 /// 32-bit UUID
109 #[derive(PartialEq, Eq, Hash)]
110 pub struct Uuid32 {
111     /// Big-endian bytes
112     uuid: [u8; 4],
113 }
114 
115 impl Uuid32 {
116     /// The UUID in big-endian bytes form
as_bytes(&self) -> [u8; 4]117     pub fn as_bytes(&self) -> [u8; 4] {
118         self.uuid
119     }
120 
parse(input: &[u8]) -> nom::IResult<&[u8], Self>121     pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Self> {
122         combinator::map_res(bytes::complete::take(4_usize), |b: &[u8]| {
123             b.try_into().map(|mut uuid: [u8; 4]| {
124                 uuid.reverse();
125                 Self { uuid }
126             })
127         })(input)
128     }
129 }
130 
131 impl fmt::Debug for Uuid32 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result132     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133         write!(f, "UUID-32:{}", hex::encode_upper(self.uuid))
134     }
135 }
136 
137 impl From<Uuid16> for Uuid32 {
from(value: Uuid16) -> Self138     fn from(value: Uuid16) -> Self {
139         let mut uuid = [0; 4];
140         uuid[2..].copy_from_slice(&value.uuid);
141         Self { uuid }
142     }
143 }
144 
145 /// 128-bit UUID
146 #[derive(PartialEq, Eq, Hash)]
147 pub struct Uuid128 {
148     /// Big-endian bytes
149     uuid: [u8; 16],
150 }
151 
152 impl Uuid128 {
153     /// The UUID in big-endian bytes form
as_bytes(&self) -> [u8; 16]154     pub fn as_bytes(&self) -> [u8; 16] {
155         self.uuid
156     }
157 
parse_le(input: &[u8]) -> nom::IResult<&[u8], Self>158     pub(crate) fn parse_le(input: &[u8]) -> nom::IResult<&[u8], Self> {
159         combinator::map_res(bytes::complete::take(16_usize), |b: &[u8]| {
160             b.try_into().map(|mut uuid: [u8; 16]| {
161                 uuid.reverse();
162                 Self { uuid }
163             })
164         })(input)
165     }
166 }
167 
168 impl fmt::Debug for Uuid128 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result169     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170         write!(
171             f,
172             "{}-{}-{}-{}-{}",
173             hex::encode_upper(&self.uuid[..4]),
174             hex::encode_upper(&self.uuid[4..6]),
175             hex::encode_upper(&self.uuid[6..8]),
176             hex::encode_upper(&self.uuid[8..10]),
177             hex::encode_upper(&self.uuid[10..])
178         )
179     }
180 }
181 
182 impl From<Uuid16> for Uuid128 {
from(value: Uuid16) -> Self183     fn from(value: Uuid16) -> Self {
184         let mut uuid = *BASE_UUID;
185         uuid[2..4].copy_from_slice(&value.uuid);
186         Self { uuid }
187     }
188 }
189 
190 impl From<Uuid32> for Uuid128 {
from(value: Uuid32) -> Self191     fn from(value: Uuid32) -> Self {
192         let mut uuid = *BASE_UUID;
193         uuid[..4].copy_from_slice(&value.uuid);
194         Self { uuid }
195     }
196 }
197