Skip to content

Commit

Permalink
Add named descriptor handles to service to make them accessible
Browse files Browse the repository at this point in the history
  • Loading branch information
petekubiak committed Feb 25, 2025
1 parent 1705aba commit b699d7e
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions host-macros/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use darling::{Error, FromMeta};
use inflector::cases::screamingsnakecase::to_screaming_snake_case;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote, quote_spanned};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::parse::Result;
use syn::spanned::Spanned;
use syn::{Expr, Meta, Token};
Expand Down Expand Up @@ -179,7 +179,7 @@ impl ServiceBuilder {

/// Construct instructions for adding a characteristic to the service, with static storage.
fn construct_characteristic_static(&mut self, characteristic: Characteristic) {
let descriptors = self.build_descriptors(&characteristic);
let (code_descriptors, named_descriptors) = self.build_descriptors(&characteristic);
let name_screaming = format_ident!("{}", to_screaming_snake_case(characteristic.name.as_str()));
let char_name = format_ident!("{}", characteristic.name);
let ty = characteristic.ty;
Expand All @@ -192,16 +192,16 @@ impl ServiceBuilder {
};

self.code_build_chars.extend(quote_spanned! {characteristic.span=>
let #char_name = {
let (#char_name, #(#named_descriptors),*) = {
static #name_screaming: static_cell::StaticCell<[u8; <#ty as trouble_host::types::gatt_traits::ToGatt>::MAX_SIZE]> = static_cell::StaticCell::new();
let mut val = <#ty>::default(); // constrain the type of the value here
val = #default_value; // update the temporary value with our new default
let store = #name_screaming.init([0; <#ty as trouble_host::types::gatt_traits::ToGatt>::MAX_SIZE]);
let mut builder = service
.add_characteristic(#uuid, &[#(#properties),*], val, store);
#descriptors
#code_descriptors

builder.build()
(builder.build(), #(#named_descriptors),*)
};
});

Expand Down Expand Up @@ -271,15 +271,17 @@ impl ServiceBuilder {
}

/// Generate token stream for any descriptors tagged against this characteristic.
fn build_descriptors(&mut self, characteristic: &Characteristic) -> TokenStream2 {
characteristic
fn build_descriptors(&mut self, characteristic: &Characteristic) -> (TokenStream2, Vec<TokenStream2>) {
let mut named_descriptors = Vec::<TokenStream2>::new();
(characteristic
.args
.descriptors
.iter()
.enumerate()
.map(|(index, args)| {
let name_screaming =
format_ident!("DESC_{index}_{}", to_screaming_snake_case(characteristic.name.as_str()));
let identifier = args.name.as_ref().map(|name| format_ident!("{}_{}_descriptor", characteristic.name.as_str(), name.value()));
let access = &args.access;
let properties = set_access_properties(access);
let uuid = &args.uuid;
Expand All @@ -289,28 +291,41 @@ impl ServiceBuilder {
};
let capacity = match &args.capacity {
Some(cap) => quote!(#cap),
None => quote!(#default_value.len() as u8)
None => quote!(#default_value.len() as usize)
};

let mut identifier_assignment = None;
if let Some(name) = &identifier {
self.code_fields.extend(quote_spanned!{ identifier.span() =>
#name: trouble_host::attribute::Descriptor<&'static [u8]>,
});
self.code_struct_init.extend(quote_spanned! { identifier.span() =>
#name,
});
named_descriptors.push(name.to_token_stream());
identifier_assignment = Some(quote! { let #name = });
};

self.attribute_count += 1; // descriptors should always only be one attribute.

quote_spanned! {characteristic.span=>
{
#identifier_assignment {
let value = #default_value;
const CAPACITY: u8 = if (#capacity) < 16 { 16 } else { #capacity }; // minimum capacity is 16 bytes
static #name_screaming: static_cell::StaticCell<[u8; CAPACITY as usize]> = static_cell::StaticCell::new();
let store = #name_screaming.init([0; CAPACITY as usize]);
const CAPACITY: usize = if (#capacity) < 16 { 16 } else { #capacity }; // minimum capacity is 16 bytes
static #name_screaming: static_cell::StaticCell<[u8; CAPACITY]> = static_cell::StaticCell::new();
let store = #name_screaming.init([0; CAPACITY]);
let value = trouble_host::types::gatt_traits::ToGatt::to_gatt(&value);
store[..value.len()].copy_from_slice(value);
builder.add_descriptor(
builder.add_descriptor::<&[u8], _>(
#uuid,
&[#(#properties),*],
store,
);
)
};
}
})
.collect()
.collect(),
named_descriptors)
}
}

Expand Down

0 comments on commit b699d7e

Please sign in to comment.