1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//! Blockz derive. #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(feature = "configuration")] #[cfg_attr(docsrs, doc(cfg(feature = "configuration")))] mod configuration; #[cfg(feature = "singleton")] #[cfg_attr(docsrs, doc(cfg(feature = "singleton")))] mod singleton; mod common; mod errors; mod factory; mod paths; use proc_macro::TokenStream; use syn::parse_macro_input; use syn::DeriveInput; use syn::ItemFn; use self::configuration::ConfigurationFactory; use self::errors::ProcMacroErrorExt; use self::factory::Factory; use self::singleton::SingletonFactory; use self::singleton::SingletonFnFactory; /// Use a factory to produce a token stream. macro_rules! factory { ($new_factory_stmt: expr) => { $new_factory_stmt .map_or_else( |mut err| err.as_compile_errors(), |factory| { factory .build() .unwrap_or_else(|mut err| err.as_compile_errors()) }, ) .into() }; } /// Derive the Singleton trait. /// /// This requires that the struct or enum is [Send]. /// /// This derive procedural macro accepts an attribute: `#[singleton]`. The attribute may configure /// the underlying lock used for securing access to the singleton. Valid values: /// /// - `#[singleton(lock = "mutex")]` _(default)_ /// - `#[singleton(lock = "rwlock")]` /// /// Required available imports: /// - [anyhow] /// - [async_trait] /// - [blockz] /// - [once_cell] /// - [tokio] /// /// [Send]: https://doc.rust-lang.org/stable/std/marker/trait.Send.html /// [anyhow]: https://docs.rs/anyhow /// [async_trait]: https://docs.rs/async_trait /// [blockz]: https://github.com/selftechio/blockz /// [once_cell]: https://docs.rs/once_cell /// [tokio]: https://docs.rs/tokio #[proc_macro_derive(Singleton, attributes(singleton))] #[cfg(feature = "singleton")] #[cfg_attr(docsrs, doc(cfg(feature = "singleton")))] pub fn derive_singleton(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); factory!(SingletonFactory::new(&input)) } /// Modify a method on a type that implements the Singleton trait. /// /// The modified method becomes a function that will use the underlying singleton. /// /// The input function must have the following properties: /// /// - the first argument must be a reference receiver (&self or &mut self) /// - function arguments identifiers must not conflict with other identifiers from the function body /// (such as other function names in function calls, struct fields etc) /// - references are not allowed (use Box\<T\> or Arc\<T\> instead) #[proc_macro_attribute] #[cfg(feature = "singleton")] #[cfg_attr(docsrs, doc(cfg(feature = "singleton")))] pub fn singleton_fn(_: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as ItemFn); factory!(SingletonFnFactory::new(&input)) } /// Derive the Configuration trait. /// /// This requires that the struct or enum is [Send]. /// /// Configuring the implementation is done via the `#[configuration]` attribute: /// /// - by default, direct configuration will be implemented, if no other configuration feature is /// enabled /// - direct configuration: `#[configuration(direct)]` /// - env configuration with no prefix: `#[configuraton(env())]` /// - env configuration with a prefix: `#[configuraton(env(prefix = "MY_PREFIX"))]` /// - env configuration with a prefix source: `#[configuraton(env(prefix_source = "MY_SOURCE"))]` /// /// The prefix source will be interpreted as an expression that will be used to source the prefix. /// You can use either constants or functions. /// /// Required available imports: /// - [anyhow] /// - [async_trait] /// - [blockz] /// - [config] /// /// [Send]: https://doc.rust-lang.org/stable/std/marker/trait.Send.html /// [anyhow]: https://docs.rs/anyhow /// [async_trait]: https://docs.rs/async_trait /// [blockz]: https://github.com/selftechio/blockz /// [config]: https://docs.rs/config #[proc_macro_derive(Configuration, attributes(configuration))] #[cfg(feature = "configuration")] #[cfg_attr(docsrs, doc(cfg(feature = "configuration")))] pub fn derive_configuration(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); factory!(ConfigurationFactory::new(input)) }