1 // Copyright 2022 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 //! Data types shared between V0 and V1 advertisements 16 17 /// Power in dBm, calibrated as per 18 /// [Eddystone](https://github.com/google/eddystone/tree/master/eddystone-uid#tx-power) 19 #[derive(Debug, PartialEq, Eq, Clone, Copy)] 20 pub struct TxPower { 21 /// Power in `[-100, 20]` 22 power: i8, 23 } 24 25 impl TxPower { 26 /// Power in `[-100, 20]` as_i8(&self) -> i827 pub fn as_i8(&self) -> i8 { 28 self.power 29 } 30 } 31 32 impl TryFrom<i8> for TxPower { 33 type Error = TxPowerOutOfRange; 34 try_from(value: i8) -> Result<Self, Self::Error>35 fn try_from(value: i8) -> Result<Self, Self::Error> { 36 if !(-100..=20).contains(&value) { 37 Err(TxPowerOutOfRange) 38 } else { 39 Ok(TxPower { power: value }) 40 } 41 } 42 } 43 44 /// Tx power was out of the valid range `[-100, 20]`. 45 #[derive(Debug, PartialEq, Eq)] 46 pub struct TxPowerOutOfRange; 47 48 /// MDP's context sync number, used to inform other devices that they have stale context. 49 #[derive(Debug, PartialEq, Eq, Clone, Copy)] 50 pub struct ContextSyncSeqNum { 51 /// 4-bit sequence 52 num: u8, 53 } 54 55 impl ContextSyncSeqNum { 56 /// Returns the context seq num as a u8 as_u8(&self) -> u857 pub fn as_u8(&self) -> u8 { 58 self.num 59 } 60 } 61 62 impl TryFrom<u8> for ContextSyncSeqNum { 63 type Error = ContextSyncSeqNumOutOfRange; 64 try_from(value: u8) -> Result<Self, Self::Error>65 fn try_from(value: u8) -> Result<Self, Self::Error> { 66 // must only have low nibble 67 if value > 0x0F { 68 Err(ContextSyncSeqNumOutOfRange) 69 } else { 70 Ok(ContextSyncSeqNum { num: value }) 71 } 72 } 73 } 74 75 /// Seq num must be in `[0-15]`. 76 #[derive(Debug, PartialEq, Eq)] 77 pub struct ContextSyncSeqNumOutOfRange; 78 79 #[allow(clippy::unwrap_used)] 80 #[cfg(test)] 81 mod tests { 82 use super::*; 83 84 #[test] tx_power_out_of_range()85 fn tx_power_out_of_range() { 86 assert_eq!(TxPowerOutOfRange, TxPower::try_from(-101).unwrap_err()); 87 assert_eq!(TxPowerOutOfRange, TxPower::try_from(21).unwrap_err()); 88 } 89 90 #[test] tx_power_ok()91 fn tx_power_ok() { 92 assert_eq!(-100, TxPower::try_from(-100).unwrap().power); 93 assert_eq!(20, TxPower::try_from(20).unwrap().power); 94 } 95 96 #[test] context_sync_seq_num_out_of_range()97 fn context_sync_seq_num_out_of_range() { 98 assert_eq!(ContextSyncSeqNumOutOfRange, ContextSyncSeqNum::try_from(0x10).unwrap_err()); 99 } 100 101 #[test] context_sync_seq_num_ok()102 fn context_sync_seq_num_ok() { 103 assert_eq!(0x0F, ContextSyncSeqNum::try_from(0x0F).unwrap().num); 104 } 105 } 106