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}