rubble/att/
handle.rs

1//! Attribute handles.
2
3use crate::att::{AttError, ErrorCode};
4use crate::{bytes::*, Error};
5use core::{fmt, ops::RangeInclusive};
6
7/// A 16-bit handle uniquely identifying an attribute on an ATT server.
8///
9/// The `0x0000` handle (`NULL`) is invalid and must not be used.
10#[derive(Copy, Clone, PartialEq, Eq)]
11pub struct Handle(u16);
12
13impl Handle {
14    /// The `0x0000` handle is not used for actual attributes, but as a special placeholder when no
15    /// attribute handle is valid (eg. in error responses).
16    pub const NULL: Self = Handle(0x0000);
17
18    /// Returns the raw 16-bit integer representing this handle.
19    pub fn as_u16(&self) -> u16 {
20        self.0
21    }
22
23    /// Create an attribute handle from a raw u16
24    pub fn from_raw(raw: u16) -> Self {
25        Handle(raw)
26    }
27}
28
29impl fmt::Debug for Handle {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(f, "{:#06X}", self.0)
32    }
33}
34
35impl FromBytes<'_> for Handle {
36    fn from_bytes(bytes: &mut ByteReader<'_>) -> Result<Self, Error> {
37        Ok(Handle(bytes.read_u16_le()?))
38    }
39}
40
41impl ToBytes for Handle {
42    fn to_bytes(&self, writer: &mut ByteWriter<'_>) -> Result<(), Error> {
43        writer.write_u16_le(self.as_u16())?;
44        Ok(())
45    }
46}
47
48/// A (de)serializable handle range that isn't checked for validity.
49#[derive(Debug, Copy, Clone)]
50pub struct RawHandleRange {
51    start: Handle,
52    end: Handle,
53}
54
55impl RawHandleRange {
56    /// Checks that this handle range is valid according to the Bluetooth spec.
57    ///
58    /// Returns an `AttError` that should be sent as a response if the range is invalid.
59    pub fn check(&self) -> Result<HandleRange, AttError> {
60        if self.start.0 > self.end.0 || self.start.0 == 0 {
61            Err(AttError::new(ErrorCode::InvalidHandle, self.start))
62        } else {
63            Ok(HandleRange(self.start..=self.end))
64        }
65    }
66}
67
68impl FromBytes<'_> for RawHandleRange {
69    fn from_bytes(bytes: &mut ByteReader<'_>) -> Result<Self, Error> {
70        Ok(Self {
71            start: Handle::from_bytes(bytes)?,
72            end: Handle::from_bytes(bytes)?,
73        })
74    }
75}
76
77impl ToBytes for RawHandleRange {
78    fn to_bytes(&self, writer: &mut ByteWriter<'_>) -> Result<(), Error> {
79        writer.write_u16_le(self.start.as_u16())?;
80        writer.write_u16_le(self.end.as_u16())?;
81        Ok(())
82    }
83}
84
85/// A (de)serializable handle range that has been checked for validity.
86#[derive(Debug)]
87pub struct HandleRange(RangeInclusive<Handle>);
88
89impl HandleRange {
90    pub fn new(from: Handle, to: Handle) -> Self {
91        HandleRange(from..=to)
92    }
93
94    /// Checks if an Handle is in a HandleRange
95    pub fn contains(&self, handle: Handle) -> bool {
96        self.0.start().0 <= handle.as_u16() && self.0.end().0 >= handle.as_u16()
97    }
98
99    /// Returns the lowest attribute handle value included in the range.
100    pub fn start(&self) -> Handle {
101        *self.0.start()
102    }
103
104    /// Returns the last (highest) attribute handle value included in the range.
105    pub fn end(&self) -> Handle {
106        *self.0.end()
107    }
108}