ble_data_struct/windows/descriptors/
windows_client_characteristic_configuration.rs

1//! Client Characteristic Configuration (Attribute Type: 0x2902) module for windows.
2
3#[cfg(target_os = "windows")]
4use windows::{
5    Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue,
6    Storage::Streams::IBuffer,
7};
8
9#[cfg(target_os = "windows")]
10use crate::{
11    descriptors::client_characteristic_configuration::ClientCharacteristicConfiguration,
12    windows::buffer::{i_buffer_to_vec, vec_to_i_buffer},
13};
14
15#[cfg(target_os = "windows")]
16impl TryFrom<&GattClientCharacteristicConfigurationDescriptorValue>
17    for ClientCharacteristicConfiguration
18{
19    type Error = String;
20    /// Create [`ClientCharacteristicConfiguration`] from [`GattClientCharacteristicConfigurationDescriptorValue`].
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use windows::{
26    ///     Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue,
27    ///     Storage::Streams::DataWriter,
28    /// };
29    ///
30    /// use ble_data_struct::descriptors::client_characteristic_configuration::{
31    ///     ClientCharacteristicConfiguration, INDICATION, NOTIFICATION,
32    /// };
33    ///
34    /// let result = ClientCharacteristicConfiguration::try_from(
35    ///     &GattClientCharacteristicConfigurationDescriptorValue::None,
36    /// );
37    /// assert!(result.is_ok());
38    /// let value = result.unwrap();
39    /// assert!(!value.is_notification());
40    /// assert!(!value.is_indication());
41    ///
42    /// let result = ClientCharacteristicConfiguration::try_from(
43    ///     &GattClientCharacteristicConfigurationDescriptorValue::Notify,
44    /// );
45    /// assert!(result.is_ok());
46    /// let value = result.unwrap();
47    /// assert!(value.is_notification());
48    /// assert!(!value.is_indication());
49    ///
50    /// let result = ClientCharacteristicConfiguration::try_from(
51    ///     &GattClientCharacteristicConfigurationDescriptorValue::Indicate,
52    /// );
53    /// assert!(result.is_ok());
54    /// let value = result.unwrap();
55    /// assert!(!value.is_notification());
56    /// assert!(value.is_indication());
57    /// ```
58    fn try_from(
59        value: &GattClientCharacteristicConfigurationDescriptorValue,
60    ) -> Result<Self, String> {
61        Ok(Self {
62            configuration: u16::from_le_bytes(value.0.to_le_bytes()[0..2].try_into().unwrap()),
63        })
64    }
65}
66
67#[cfg(target_os = "windows")]
68impl TryFrom<IBuffer> for ClientCharacteristicConfiguration {
69    type Error = String;
70    /// Create [`ClientCharacteristicConfiguration`] from [`IBuffer`].
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// use windows::Storage::Streams::{DataWriter, IBuffer};
76    ///
77    /// use ble_data_struct::descriptors::client_characteristic_configuration::{
78    ///     ClientCharacteristicConfiguration, INDICATION, NOTIFICATION,
79    /// };
80    ///
81    /// let client_characteristic_configuration =
82    ///     ClientCharacteristicConfiguration::new(NOTIFICATION);
83    /// let data_writer = DataWriter::new().unwrap();
84    /// let ble_packet: Vec<u8> = client_characteristic_configuration.into();
85    /// data_writer.WriteBytes(&ble_packet).unwrap();
86    /// let buffer = data_writer.DetachBuffer().unwrap();
87
88    /// let result = ClientCharacteristicConfiguration::try_from(buffer);
89    /// assert!(result.is_ok());
90    /// let value = result.unwrap();
91    /// assert!(value.is_notification());
92    /// ```
93    fn try_from(value: IBuffer) -> Result<Self, String> {
94        let vec = i_buffer_to_vec(value).unwrap();
95        let configuration = u16::from_le_bytes(vec.try_into().unwrap());
96        Ok(Self {
97            configuration: configuration,
98        })
99    }
100}
101
102#[cfg(target_os = "windows")]
103impl Into<GattClientCharacteristicConfigurationDescriptorValue>
104    for ClientCharacteristicConfiguration
105{
106    /// Create [`GattClientCharacteristicConfigurationDescriptorValue`] from [`ClientCharacteristicConfiguration`].
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// use windows::{
112    ///     Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue,
113    ///     Storage::Streams::DataWriter,
114    /// };
115    ///
116    /// use ble_data_struct::descriptors::client_characteristic_configuration::{
117    ///     ClientCharacteristicConfiguration, INDICATION, NOTIFICATION,
118    /// };
119    ///
120    /// let value: GattClientCharacteristicConfigurationDescriptorValue =
121    ///     ClientCharacteristicConfiguration::new(0).into();
122    /// assert_eq!(
123    ///     GattClientCharacteristicConfigurationDescriptorValue::None,
124    ///     value
125    /// );
126    ///
127    /// let value: GattClientCharacteristicConfigurationDescriptorValue =
128    ///     ClientCharacteristicConfiguration::new(NOTIFICATION).into();
129    /// assert_eq!(
130    ///     GattClientCharacteristicConfigurationDescriptorValue::Notify,
131    ///     value
132    /// );
133    ///
134    /// let value: GattClientCharacteristicConfigurationDescriptorValue =
135    ///     ClientCharacteristicConfiguration::new(INDICATION).into();
136    /// assert_eq!(
137    ///     GattClientCharacteristicConfigurationDescriptorValue::Indicate,
138    ///     value
139    /// );
140    /// ```
141    fn into(self) -> GattClientCharacteristicConfigurationDescriptorValue {
142        if self.is_notification() {
143            GattClientCharacteristicConfigurationDescriptorValue::Notify
144        } else if self.is_indication() {
145            GattClientCharacteristicConfigurationDescriptorValue::Indicate
146        } else {
147            GattClientCharacteristicConfigurationDescriptorValue::None
148        }
149    }
150}
151
152#[cfg(target_os = "windows")]
153impl Into<IBuffer> for ClientCharacteristicConfiguration {
154    /// Create [`IBuffer`] from [`ClientCharacteristicConfiguration`].
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use windows::{
160    ///     Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue,
161    ///     Storage::Streams::{DataWriter, IBuffer},
162    /// };
163    ///
164    /// use ble_data_struct::{
165    ///     descriptors::client_characteristic_configuration::{
166    ///         ClientCharacteristicConfiguration, INDICATION, NOTIFICATION,
167    ///     },
168    ///     windows::buffer::i_buffer_to_vec,
169    /// };
170    ///
171    /// let value = ClientCharacteristicConfiguration::new(0);
172    /// let buffer: IBuffer = value.clone().into();
173    /// let vec: Vec<u8> = value.into();
174    /// assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
175    ///
176    /// let value = ClientCharacteristicConfiguration::new(NOTIFICATION);
177    /// let buffer: IBuffer = value.clone().into();
178    /// let vec: Vec<u8> = value.into();
179    /// assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
180    ///
181    /// let value = ClientCharacteristicConfiguration::new(INDICATION);
182    /// let buffer: IBuffer = value.clone().into();
183    /// let vec: Vec<u8> = value.into();
184    /// assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
185    /// ```
186    fn into(self) -> IBuffer {
187        let vec: Vec<u8> = self.into();
188        vec_to_i_buffer(&vec).unwrap()
189    }
190}
191
192#[cfg(target_os = "windows")]
193#[cfg(test)]
194mod tests {
195    use windows::{
196        Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue,
197        Storage::Streams::{DataWriter, IBuffer},
198    };
199
200    use crate::{
201        descriptors::client_characteristic_configuration::{
202            ClientCharacteristicConfiguration, INDICATION, NOTIFICATION,
203        },
204        windows::buffer::i_buffer_to_vec,
205    };
206
207    #[test]
208    fn test_try_from_gatt_client_characteristic_configuration_descriptor_value() {
209        let result = ClientCharacteristicConfiguration::try_from(
210            &GattClientCharacteristicConfigurationDescriptorValue::None,
211        );
212        assert!(result.is_ok());
213        let value = result.unwrap();
214        assert!(!value.is_notification());
215        assert!(!value.is_indication());
216
217        let result = ClientCharacteristicConfiguration::try_from(
218            &GattClientCharacteristicConfigurationDescriptorValue::Notify,
219        );
220        assert!(result.is_ok());
221        let value = result.unwrap();
222        assert!(value.is_notification());
223        assert!(!value.is_indication());
224
225        let result = ClientCharacteristicConfiguration::try_from(
226            &GattClientCharacteristicConfigurationDescriptorValue::Indicate,
227        );
228        assert!(result.is_ok());
229        let value = result.unwrap();
230        assert!(!value.is_notification());
231        assert!(value.is_indication());
232    }
233
234    #[test]
235    fn test_try_from_i_buffer() {
236        let client_characteristic_configuration =
237            ClientCharacteristicConfiguration::new(NOTIFICATION);
238        let data_writer = DataWriter::new().unwrap();
239        let ble_packet: Vec<u8> = client_characteristic_configuration.into();
240        data_writer.WriteBytes(&ble_packet).unwrap();
241        let buffer = data_writer.DetachBuffer().unwrap();
242
243        let result = ClientCharacteristicConfiguration::try_from(buffer);
244        assert!(result.is_ok());
245        let value = result.unwrap();
246        assert!(value.is_notification());
247    }
248
249    #[test]
250    fn test_into_gatt_client_characteristic_configuration_descriptor_value() {
251        let value: GattClientCharacteristicConfigurationDescriptorValue =
252            ClientCharacteristicConfiguration::new(0).into();
253        assert_eq!(
254            GattClientCharacteristicConfigurationDescriptorValue::None,
255            value
256        );
257
258        let value: GattClientCharacteristicConfigurationDescriptorValue =
259            ClientCharacteristicConfiguration::new(NOTIFICATION).into();
260        assert_eq!(
261            GattClientCharacteristicConfigurationDescriptorValue::Notify,
262            value
263        );
264
265        let value: GattClientCharacteristicConfigurationDescriptorValue =
266            ClientCharacteristicConfiguration::new(INDICATION).into();
267        assert_eq!(
268            GattClientCharacteristicConfigurationDescriptorValue::Indicate,
269            value
270        );
271    }
272
273    #[test]
274    fn test_into_i_buffer() {
275        let value = ClientCharacteristicConfiguration::new(0);
276        let buffer: IBuffer = value.clone().into();
277        let vec: Vec<u8> = value.into();
278        assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
279
280        let value = ClientCharacteristicConfiguration::new(NOTIFICATION);
281        let buffer: IBuffer = value.clone().into();
282        let vec: Vec<u8> = value.into();
283        assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
284
285        let value = ClientCharacteristicConfiguration::new(INDICATION);
286        let buffer: IBuffer = value.clone().into();
287        let vec: Vec<u8> = value.into();
288        assert_eq!(vec, i_buffer_to_vec(buffer).unwrap());
289    }
290}