This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/embassy-executor-macros/src/util.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

75 lines
2.3 KiB
Rust

use std::fmt::Display;
use proc_macro2::{TokenStream, TokenTree};
use quote::{ToTokens, TokenStreamExt};
use syn::parse::{Parse, ParseStream};
use syn::{braced, bracketed, token, AttrStyle, Attribute, Signature, Token, Visibility};
pub fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
tokens.extend(error.into_compile_error());
tokens
}
pub fn error<A: ToTokens, T: Display>(s: &mut TokenStream, obj: A, msg: T) {
s.extend(syn::Error::new_spanned(obj.into_token_stream(), msg).into_compile_error())
}
/// Function signature and body.
///
/// Same as `syn`'s `ItemFn` except we keep the body as a TokenStream instead of
/// parsing it. This makes the macro not error if there's a syntax error in the body,
/// which helps IDE autocomplete work better.
#[derive(Debug, Clone)]
pub struct ItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub sig: Signature,
pub brace_token: token::Brace,
pub body: TokenStream,
}
impl Parse for ItemFn {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
let content;
let brace_token = braced!(content in input);
while content.peek(Token![#]) && content.peek2(Token![!]) {
let content2;
attrs.push(Attribute {
pound_token: content.parse()?,
style: AttrStyle::Inner(content.parse()?),
bracket_token: bracketed!(content2 in content),
meta: content2.parse()?,
});
}
let mut body = Vec::new();
while !content.is_empty() {
body.push(content.parse::<TokenTree>()?);
}
let body = body.into_iter().collect();
Ok(ItemFn {
attrs,
vis,
sig,
brace_token,
body,
})
}
}
impl ToTokens for ItemFn {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.iter().filter(|a| matches!(a.style, AttrStyle::Outer)));
self.vis.to_tokens(tokens);
self.sig.to_tokens(tokens);
self.brace_token.surround(tokens, |tokens| {
tokens.append_all(self.body.clone());
});
}
}