extension_fn/
lib.rs

1//! No boilerplate code for extension function definitions.
2
3#[macro_use]
4extern crate public;
5
6use args::{Args};
7use builder::Builder;
8use syn::{
9    parse_macro_input, ItemFn,
10};
11
12mod args;
13mod builder;
14
15
16/// Extension function macro. Example usage:
17/// ```rust
18/// use extension_fn::extension_fn;
19///
20/// // Also you can change pub to anything e.g. pub(crate) to make this function public only for current crate.
21/// #[extension_fn(str)]
22/// pub fn count_numbers(&self) -> u32 {
23///     self.chars().fold(0, |count, char| {
24///        if char.is_numeric() {
25///         count + 1
26///        } else {
27///           count
28///        }
29///    })
30/// }
31/// ```
32/// Example with async function(you should add async-trait to your dependencies`):
33/// ```rust
34/// use extension_fn::extension_fn;
35/// use std::net::TcpStream;
36///
37/// #[extension_fn(TcpStream)]
38/// pub async fn do_something() {}
39/// ```
40/// Example for trait bound:
41/// ```rust
42/// use extension_fn::extension_fn;
43///
44/// #[extension_fn(trait AsRef<str>)]
45/// fn print(&self) {
46///     println!("{}", self.as_ref());
47/// }
48/// ```
49/// Example for generics:
50/// ```rust
51/// use extension_fn::extension_fn;
52/// use std::hash::Hash;
53/// use std::collections::HashMap;
54/// 
55/// #[extension_fn(<K: Hash + Eq, V> HashMap<K, V>)]
56/// fn insert_if_not_exists(&mut self, key: K, value: V) {
57///     if self.get(&key).is_none() {
58///        self.insert(key, value);
59///     }
60/// }
61/// ```
62#[proc_macro_attribute]
63pub fn extension_fn(
64    args: proc_macro::TokenStream,
65    input: proc_macro::TokenStream,
66) -> proc_macro::TokenStream {
67    let args = parse_macro_input!(args as Args);
68    let fn_implementation = parse_macro_input!(input as ItemFn);
69    Builder::new(&fn_implementation.sig.ident).build(fn_implementation, args).into()
70}