-
Notifications
You must be signed in to change notification settings - Fork 366
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Previously, we used the `bdk_macros` dependency for some simple proc macros in `lightning-transaction-sync`. However, post-1.0 BDK doesn't further maintain this crate and will at some point probably yank it together with the old `bdk` crate that was split up. Here, we create a new crate for utility proc macros and ~~steal~~ add what we currently use (slightly modified for the latest `syn` version's API though). In the future we may want to expand this crate, e.g., for some `maybe_async` macros in the context of an `async KVStore` implementation.
- Loading branch information
Showing
4 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[package] | ||
name = "lightning-macros" | ||
version = "0.1.0" | ||
authors = ["Elias Rohrer"] | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/lightningdevkit/rust-lightning/" | ||
description = """ | ||
Proc macros used by LDK | ||
""" | ||
edition = "2021" | ||
|
||
[package.metadata.docs.rs] | ||
rustdoc-args = ["--cfg", "docsrs"] | ||
|
||
[lib] | ||
proc-macro = true | ||
|
||
[features] | ||
|
||
[dependencies] | ||
syn = { version = "2.0.77", default-features = false, features = ["parsing", "printing", "proc-macro", "full"] } | ||
proc-macro2 = { version = "1.0.86", default-features = false, features = ["proc-macro"] } | ||
quote = { version = "1.0", default-features = false, features = ["proc-macro"] } | ||
|
||
[lints] | ||
workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// This file is Copyright its original authors, visible in version control | ||
// history. | ||
// | ||
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE | ||
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. | ||
// You may not use this file except in accordance with one or both of these | ||
// licenses. | ||
|
||
#![crate_name = "lightning_macros"] | ||
|
||
//! Proc macros used by LDK | ||
|
||
#![cfg_attr(not(test), no_std)] | ||
#![deny(missing_docs)] | ||
#![forbid(unsafe_code)] | ||
#![deny(rustdoc::broken_intra_doc_links)] | ||
#![deny(rustdoc::private_intra_doc_links)] | ||
#![cfg_attr(docsrs, feature(doc_auto_cfg))] | ||
|
||
use proc_macro::TokenStream; | ||
use quote::quote; | ||
use syn::spanned::Spanned; | ||
use syn::{parse, ImplItemFn, ItemImpl, ItemTrait, Token}; | ||
|
||
fn add_async_trait(mut parsed: ItemTrait) -> TokenStream { | ||
let output = quote! { | ||
#[cfg(not(feature = "async-interface"))] | ||
#parsed | ||
}; | ||
|
||
for mut item in &mut parsed.items { | ||
if let syn::TraitItem::Fn(f) = &mut item { | ||
f.sig.asyncness = Some(Token![async](f.span())); | ||
} | ||
} | ||
|
||
let output = quote! { | ||
#output | ||
|
||
#[cfg(feature = "async-interface")] | ||
#[async_trait(?Send)] | ||
#parsed | ||
}; | ||
|
||
output.into() | ||
} | ||
|
||
fn add_async_method(mut parsed: ImplItemFn) -> TokenStream { | ||
let output = quote! { | ||
#[cfg(not(feature = "async-interface"))] | ||
#parsed | ||
}; | ||
|
||
parsed.sig.asyncness = Some(Token![async](parsed.span())); | ||
|
||
let output = quote! { | ||
#output | ||
|
||
#[cfg(feature = "async-interface")] | ||
#parsed | ||
}; | ||
|
||
output.into() | ||
} | ||
|
||
fn add_async_impl_trait(mut parsed: ItemImpl) -> TokenStream { | ||
let output = quote! { | ||
#[cfg(not(feature = "async-interface"))] | ||
#parsed | ||
}; | ||
|
||
for mut item in &mut parsed.items { | ||
if let syn::ImplItem::Fn(f) = &mut item { | ||
f.sig.asyncness = Some(Token![async](f.span())); | ||
} | ||
} | ||
|
||
let output = quote! { | ||
#output | ||
|
||
#[cfg(feature = "async-interface")] | ||
#[async_trait(?Send)] | ||
#parsed | ||
}; | ||
|
||
output.into() | ||
} | ||
|
||
/// Makes a method or every method of a trait `async`, if the `async-interface` feature is enabled. | ||
/// | ||
/// Requires the `async-trait` crate as a dependency whenever this attribute is used on a trait | ||
/// definition or trait implementation. | ||
#[proc_macro_attribute] | ||
pub fn maybe_async(_attr: TokenStream, item: TokenStream) -> TokenStream { | ||
if let Ok(parsed) = parse(item.clone()) { | ||
add_async_trait(parsed) | ||
} else if let Ok(parsed) = parse(item.clone()) { | ||
add_async_method(parsed) | ||
} else if let Ok(parsed) = parse(item) { | ||
add_async_impl_trait(parsed) | ||
} else { | ||
(quote! { | ||
compile_error!("#[maybe_async] can only be used on methods, trait or trait impl blocks") | ||
}) | ||
.into() | ||
} | ||
} | ||
|
||
/// Awaits, if the `async-interface` feature is enabled. | ||
#[proc_macro] | ||
pub fn maybe_await(expr: TokenStream) -> TokenStream { | ||
let expr: proc_macro2::TokenStream = expr.into(); | ||
let quoted = quote! { | ||
{ | ||
#[cfg(not(feature = "async-interface"))] | ||
{ | ||
#expr | ||
} | ||
|
||
#[cfg(feature = "async-interface")] | ||
{ | ||
#expr.await | ||
} | ||
} | ||
}; | ||
|
||
quoted.into() | ||
} |