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