Skip to content

Commit

Permalink
Merge pull request #28 from bjoernQ/de-duplicate-code
Browse files Browse the repository at this point in the history
De duplicate code
  • Loading branch information
bjoernQ authored Dec 4, 2023
2 parents 473dea6 + 6ded287 commit 5e70db0
Show file tree
Hide file tree
Showing 6 changed files with 558 additions and 821 deletions.
17 changes: 17 additions & 0 deletions bleps-dedup/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "bleps-dedup"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
quote = "1.0"
proc-macro2 = "1.0"
proc-macro-error = "1.0.4"
syn = { version = "2.0.39", features = ["full"] }
darling = "0.20.3"

[features]
generate-async = []
139 changes: 139 additions & 0 deletions bleps-dedup/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use proc_macro::TokenStream;
use proc_macro_error::proc_macro_error;

#[derive(Debug)]
struct Implementation {
is_async: bool,
tokens: TokenStream,
}

/// A macro to de-duplicate SYNC / ASYNC code loosely inspired by maybe-async
#[proc_macro]
#[proc_macro_error]
pub fn dedup(input: TokenStream) -> TokenStream {
let mut impls: Vec<Implementation> = Vec::new();
let mut body = None;
let mut impl_is_async = false;

let mut current = TokenStream::new();
for token in input.into_iter() {
let tok = token.clone();
match token {
proc_macro::TokenTree::Ident(ident) => match ident.to_string().as_str() {
"impl" => {
if !current.is_empty() {
impls.push(Implementation {
is_async: impl_is_async,
tokens: current,
})
}
current = TokenStream::new();
current.extend([tok]);
}
"SYNC" => {
impl_is_async = false;
}
"ASYNC" => {
impl_is_async = true;
}
_ => {
current.extend([tok]);
}
},
proc_macro::TokenTree::Group(_group) => {
if !current.is_empty() {
impls.push(Implementation {
is_async: impl_is_async,
tokens: current.clone(),
})
}

let mut stream = TokenStream::new();
stream.extend([tok]);
body = Some(stream);
}
_ => {
current.extend([tok]);
}
}
}

let mut generated = Vec::new();
for imp in impls {
#[cfg(not(feature = "generate-async"))]
if imp.is_async {
continue;
}

let decl: proc_macro2::TokenStream = imp.tokens.into();
let block: proc_macro2::TokenStream = if !imp.is_async {
de_async(body.clone().unwrap().into())
} else {
body.clone().unwrap().into()
};

generated.push(quote::quote!(
#decl
#block
));
}

quote::quote!(
#(#generated)*
)
.into()
}

fn de_async(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
let mut output = proc_macro2::TokenStream::new();

let mut prev = None;
for token in input.into_iter() {
let tok = token.clone();
match token {
proc_macro2::TokenTree::Ident(ident) => {
if match ident.to_string().as_str() {
"await" => {
prev = None;
false
}
"async" => false,
_ => true,
} {
if let Some(prev) = prev.clone() {
output.extend([prev]);
}
prev = None;
output.extend([tok]);
}
}
proc_macro2::TokenTree::Punct(p) => {
if p.as_char() == '.' {
prev = Some(tok);
} else {
output.extend([tok]);
}
}
proc_macro2::TokenTree::Group(group) => {
if let Some(prev) = prev.clone() {
output.extend([prev]);
}
prev = None;

let converted = de_async(group.stream());
let group = proc_macro2::Group::new(group.delimiter(), converted);
let group = proc_macro2::TokenTree::Group(group);
output.extend([group]);
}
_ => {
if let Some(prev) = prev.clone() {
output.extend([prev]);
}
prev = None;
output.extend([tok]);
}
}
}

output
}
4 changes: 3 additions & 1 deletion bleps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ categories = [
]

[dependencies]
bleps-dedup = { path = "../bleps-dedup" }

log = "0.4.16"
embedded-io-blocking = { package = "embedded-io", version = "0.6.1" }
embedded-io-async = { version = "0.6.0", optional = true }
Expand All @@ -29,7 +31,7 @@ bleps-macros = { path = "../bleps-macros", optional = true }
env_logger = "0.10.0"

[features]
async = [ "dep:embedded-io-async", "dep:futures", "dep:critical-section" ]
async = [ "dep:embedded-io-async", "dep:futures", "dep:critical-section", "bleps-dedup/generate-async" ]
macros = [ "bleps-macros" ]
defmt = [ "dep:defmt" ]
mtu128 = []
Expand Down
Loading

0 comments on commit 5e70db0

Please sign in to comment.