diff --git a/rubble/src/att/mod.rs b/rubble/src/att/mod.rs index b855f11eb..51cea7d1f 100644 --- a/rubble/src/att/mod.rs +++ b/rubble/src/att/mod.rs @@ -35,42 +35,62 @@ mod server; mod uuid; use self::{handle::*, pdus::*}; -use crate::{utils::HexSlice, Error}; +use crate::Error; pub use self::handle::{Handle, HandleRange}; pub use self::server::{AttributeServer, AttributeServerTx}; pub use self::uuid::AttUuid; +/// An attribute value that can be represented as a byte slice. +pub trait AttrValue { + fn as_slice(&self) -> &[u8]; +} + +impl AttrValue for &[u8] { + fn as_slice(&self) -> &[u8] { + self + } +} + +impl AttrValue for () { + fn as_slice(&self) -> &[u8] { + &[] + } +} + /// An ATT server attribute -pub struct Attribute<'a> { +pub struct Attribute +where + T: ?Sized, +{ /// The type of the attribute as a UUID16, EG "Primary Service" or "Anaerobic Heart Rate Lower Limit" pub att_type: AttUuid, /// Unique server-side identifer for attribute pub handle: Handle, /// Attribute values can be any fixed length or variable length octet array, which if too large /// can be sent across multiple PDUs - pub value: HexSlice<&'a [u8]>, + pub value: T, } -impl<'a> Attribute<'a> { +impl Attribute { /// Creates a new attribute. - pub fn new(att_type: AttUuid, handle: Handle, value: &'a [u8]) -> Self { + pub fn new(att_type: AttUuid, handle: Handle, value: T) -> Self { assert_ne!(handle, Handle::NULL); Attribute { att_type, handle, - value: HexSlice(value), + value: value, } } /// Retrieves the attribute's value as a slice. - pub fn value(&self) -> &'a [u8] { - self.value.as_ref() + pub fn value(&self) -> &[u8] { + self.value.as_slice() } /// Overrides the previously set attribute's value. - pub fn set_value(&mut self, value: &'a [u8]) { - self.value = HexSlice(value) + pub fn set_value(&mut self, value: T) { + self.value = value; } } @@ -87,7 +107,7 @@ pub trait AttributeProvider { fn for_attrs_in_range( &mut self, range: HandleRange, - f: impl FnMut(&Self, Attribute<'_>) -> Result<(), Error>, + f: impl FnMut(&Self, &Attribute) -> Result<(), Error>, ) -> Result<(), Error>; /// Returns whether `uuid` is a valid grouping attribute type that can be used in *Read By @@ -109,7 +129,7 @@ pub trait AttributeProvider { /// last attribute contained within that service. /// /// TODO: document what the BLE spec has to say about grouping for characteristics. - fn group_end(&self, handle: Handle) -> Option<&Attribute<'_>>; + fn group_end(&self, handle: Handle) -> Option<&Attribute>; } /// An empty attribute set. @@ -121,7 +141,7 @@ impl AttributeProvider for NoAttributes { fn for_attrs_in_range( &mut self, _range: HandleRange, - _f: impl FnMut(&Self, Attribute<'_>) -> Result<(), Error>, + _f: impl FnMut(&Self, &Attribute) -> Result<(), Error>, ) -> Result<(), Error> { Ok(()) } @@ -130,7 +150,7 @@ impl AttributeProvider for NoAttributes { false } - fn group_end(&self, _handle: Handle) -> Option<&Attribute<'_>> { + fn group_end(&self, _handle: Handle) -> Option<&Attribute> { None } } diff --git a/rubble/src/att/server.rs b/rubble/src/att/server.rs index a7acba0e8..6117a59d2 100644 --- a/rubble/src/att/server.rs +++ b/rubble/src/att/server.rs @@ -99,7 +99,7 @@ impl AttributeServer { .for_attrs_in_range(range, |_provider, attr| { if attr.att_type == *attribute_type { let data = - ByTypeAttData::new(att_mtu, attr.handle, attr.value.as_ref()); + ByTypeAttData::new(att_mtu, attr.handle, attr.value.as_slice()); if size == Some(data.encoded_size()) || size.is_none() { // Can try to encode `data`. If we run out of space, end the list. data.to_bytes(writer)?; @@ -156,7 +156,7 @@ impl AttributeServer { att_mtu, attr.handle, provider.group_end(attr.handle).unwrap().handle, - attr.value.as_ref(), + attr.value.as_slice(), ); if size == Some(data.encoded_size()) || size.is_none() { // Can try to encode `data`. If we run out of space, end the list. @@ -197,10 +197,10 @@ impl AttributeServer { self.attrs.for_attrs_in_range( HandleRange::new(*handle, *handle), |_provider, attr| { - let value = if writer.space_left() < attr.value.as_ref().len() { - &attr.value.as_ref()[..writer.space_left()] + let value = if writer.space_left() < attr.value.as_slice().len() { + &attr.value.as_slice()[..writer.space_left()] } else { - attr.value.as_ref() + attr.value.as_slice() }; writer.write_slice(value) }, diff --git a/rubble/src/gatt/mod.rs b/rubble/src/gatt/mod.rs index f11def283..acd6e12f3 100644 --- a/rubble/src/gatt/mod.rs +++ b/rubble/src/gatt/mod.rs @@ -5,14 +5,14 @@ pub mod characteristic; -use crate::att::{AttUuid, Attribute, AttributeProvider, Handle, HandleRange}; +use crate::att::{AttUuid, AttrValue, Attribute, AttributeProvider, Handle, HandleRange}; use crate::uuid::{Uuid128, Uuid16}; use crate::Error; -use core::{cmp, slice}; +use core::cmp; /// A demo `AttributeProvider` that will enumerate as a *Battery Service*. pub struct BatteryServiceAttrs { - attributes: [Attribute<'static>; 3], + attributes: [Attribute<&'static [u8]>; 3], } impl BatteryServiceAttrs { @@ -48,7 +48,7 @@ impl AttributeProvider for BatteryServiceAttrs { fn for_attrs_in_range( &mut self, range: HandleRange, - mut f: impl FnMut(&Self, Attribute<'_>) -> Result<(), Error>, + mut f: impl FnMut(&Self, &Attribute) -> Result<(), Error>, ) -> Result<(), Error> { let count = self.attributes.len(); let start = usize::from(range.start().as_u16() - 1); // handles start at 1, not 0 @@ -62,14 +62,7 @@ impl AttributeProvider for BatteryServiceAttrs { }; for attr in attrs { - f( - self, - Attribute { - att_type: attr.att_type, - handle: attr.handle, - value: attr.value, - }, - )?; + f(self, attr)?; } Ok(()) } @@ -78,7 +71,7 @@ impl AttributeProvider for BatteryServiceAttrs { uuid == Uuid16(0x2800) // FIXME not characteristics? } - fn group_end(&self, handle: Handle) -> Option<&Attribute<'_>> { + fn group_end(&self, handle: Handle) -> Option<&Attribute> { match handle.as_u16() { 0x0001 => Some(&self.attributes[2]), 0x0002 => Some(&self.attributes[2]), @@ -87,27 +80,11 @@ impl AttributeProvider for BatteryServiceAttrs { } } -pub struct Attributes<'a> { - to_yield: slice::Iter<'a, Attribute<'a>>, -} - -impl<'a> Iterator for Attributes<'a> { - type Item = Attribute<'a>; - - fn next(&mut self) -> Option> { - self.to_yield.next().map(|attr| Attribute { - att_type: attr.att_type, - handle: attr.handle, - value: attr.value, - }) - } -} - /// A demo `AttributeProvider` that will enumerate as a *Midi Service*. /// /// Also refer to https://www.midi.org/specifications-old/item/bluetooth-le-midi pub struct MidiServiceAttrs { - attributes: [Attribute<'static>; 4], + attributes: [Attribute<&'static [u8]>; 4], } // MIDI Service (UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700) @@ -181,7 +158,7 @@ impl AttributeProvider for MidiServiceAttrs { fn for_attrs_in_range( &mut self, range: HandleRange, - mut f: impl FnMut(&Self, Attribute<'_>) -> Result<(), Error>, + mut f: impl FnMut(&Self, &Attribute) -> Result<(), Error>, ) -> Result<(), Error> { let count = self.attributes.len(); let start = usize::from(range.start().as_u16() - 1); // handles start at 1, not 0 @@ -195,14 +172,7 @@ impl AttributeProvider for MidiServiceAttrs { }; for attr in attrs { - f( - self, - Attribute { - att_type: attr.att_type, - handle: attr.handle, - value: attr.value, - }, - )?; + f(self, attr)?; } Ok(()) } @@ -211,7 +181,7 @@ impl AttributeProvider for MidiServiceAttrs { uuid == Uuid16(0x2800) // FIXME not characteristics? } - fn group_end(&self, handle: Handle) -> Option<&Attribute<'_>> { + fn group_end(&self, handle: Handle) -> Option<&Attribute> { match handle.as_u16() { 0x0001 => Some(&self.attributes[3]), 0x0002 => Some(&self.attributes[3]),