aboutsummaryrefslogtreecommitdiff
path: root/nearby/presence/np_adv/src/legacy/data_elements.rs
blob: e9c23081fdd6ad7cc39213ac6c925f924413d424 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! V0 data elements and core trait impls.
use crate::legacy::{
    de_type::{DataElementType, PlainDataElementType},
    serialize::{DataElementBundle, ToDataElementBundle},
    PacketFlavor, PacketFlavorEnum,
};
use crate::shared_data::*;

/// Core behavior for data elements.
///
/// See also [ToDataElementBundle] for flavor-specific, infallible serialization.
pub trait DataElement: Sized {
    /// The corresponding DataElementType variant.
    const DE_TYPE_VARIANT: DataElementType;

    /// Return true if the DE supports serialization and deserialization for the provided flavor.
    fn supports_flavor(flavor: PacketFlavorEnum) -> bool;

    /// Returns `Err` if the flavor is not supported or if parsing fails.
    ///
    /// `<F>` is the flavor of the packet being deserialized.
    fn deserialize<F: PacketFlavor>(
        de_contents: &[u8],
    ) -> Result<Self, DataElementDeserializeError>;
}

/// Errors possible when deserializing a DE
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DataElementDeserializeError {
    /// The data element doesn't support the [PacketFlavor] of the advertisement packet.
    FlavorNotSupported {
        /// The DE type attempting to be deserialized
        de_type: DataElementType,
        /// The flavor that was not supported
        flavor: PacketFlavorEnum,
    },
    /// The data element couldn't be deserialized from the supplied data.
    DeserializeError {
        /// The DE type attempting to be deserialized
        de_type: DataElementType,
    },
}

/// Data element holding a [TxPower].
#[derive(Debug, PartialEq, Eq)]
pub struct TxPowerDataElement {
    tx_power: TxPower,
}

impl TxPowerDataElement {
    /// Gets the underlying Tx Power value
    pub fn tx_power_value(&self) -> i8 {
        self.tx_power.as_i8()
    }
}

impl From<TxPower> for TxPowerDataElement {
    fn from(tx_power: TxPower) -> Self {
        Self { tx_power }
    }
}

impl<F: PacketFlavor> ToDataElementBundle<F> for TxPowerDataElement {
    fn to_de_bundle(&self) -> DataElementBundle<F> {
        let tx_power = self.tx_power.as_i8();
        DataElementBundle::try_from(
            PlainDataElementType::TxPower,
            tx_power.to_be_bytes().as_slice(),
        )
        .expect("Length < max DE size")
    }
}

impl DataElement for TxPowerDataElement {
    const DE_TYPE_VARIANT: DataElementType = DataElementType::TxPower;

    fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
        match flavor {
            PacketFlavorEnum::Plaintext => true,
            PacketFlavorEnum::Ciphertext => true,
        }
    }
    fn deserialize<F: PacketFlavor>(
        de_contents: &[u8],
    ) -> Result<Self, DataElementDeserializeError> {
        de_contents
            .try_into()
            .ok()
            .and_then(|arr: [u8; 1]| TxPower::try_from(i8::from_be_bytes(arr)).ok())
            .map(|tx_power| Self { tx_power })
            .ok_or(DataElementDeserializeError::DeserializeError {
                de_type: DataElementType::TxPower,
            })
    }
}