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
//! [![crates.io](https://meritbadge.herokuapp.com/turbonone)](https://crates.io/crates/turbonone) //! [![docs.rs](https://docs.rs/turbonone/badge.svg)](https://docs.rs/turbonone/) //! [![license](https://img.shields.io/crates/l/turbonone)](https://github.com/WilliamVenner/turbonone/blob/master/LICENSE) //! //! Simple macro for calling functions with generic `Option<T>` arguments. //! //! ## Usage //! //! Add to your [Cargo.toml](https://doc.rust-lang.org/cargo/reference/manifest.html) file: //! //! ```toml //! [dependencies] //! turbonone = "0.*" //! ``` //! //! ## The Problem //! //! ```ignore //! # extern crate core; //! # extern crate turbonone; //! # use turbonone::turbonone; //! fn my_function<T>(arg: Option<T>) -> &'static str { //! "Works!" //! } //! //! fn my_box_function<T>(arg: Option<Box<T>>) -> &'static str { //! "Works!" //! } //! //! fn my_complex_function<T>(arg: Option<Arc<Box<T>>>) -> &'static str { //! "Works!" //! } //! //! my_function(None); // cannot infer type for type parameter `T` declared on the associated function `my_function` //! my_function(Some("An argument")); // Works! //! //! my_box_function(None); // cannot infer type for type parameter `T` declared on the associated function `my_box_function` //! my_box_function(Some(Box::new("An argument"))); // Works! //! //! my_complex_function(None); // cannot infer type for type parameter `T` declared on the associated function `my_complex_function` //! my_complex_function(Some(Arc::new(Box::new("An argument")))); // Works! //! ``` //! //! ## The Solution //! //! ```rust //! # extern crate core; //! #[macro_use] extern crate turbonone; //! # use std::sync::Arc; //! //! fn my_function<T>(arg: Option<T>) -> &'static str { //! "Works!" //! } //! //! fn my_box_function<T>(arg: Option<Box<T>>) -> &'static str { //! "Works!" //! } //! //! fn my_complex_function<T>(arg: Option<Arc<Box<T>>>) -> &'static str { //! "Works!" //! } //! //! my_function(turbonone!()); // Works! //! my_function(Some("An argument")); // Works! //! //! my_box_function(turbonone!(Box)); // Works! //! my_box_function(turbonone!(Box<()>)); // Works! //! my_box_function(Some(Box::new("An argument"))); // Works! //! //! my_complex_function(turbonone!(Arc<Box<()>>)); // Works! //! my_complex_function(Some(Arc::new(Box::new("An argument")))); // Works! //! ``` #![no_std] extern crate alloc; use alloc::{format, string::ToString}; extern crate proc_macro; use proc_macro::TokenStream; #[proc_macro] pub fn turbonone(tokens: TokenStream) -> TokenStream { if tokens.is_empty() { "::core::option::Option::None::<()>".parse().unwrap() } else { let mut elided_unit_type = true; { let mut i: u8 = 0; for _ in tokens.clone().into_iter() { i += 1; if i > 1 { elided_unit_type = false; break; } } } if elided_unit_type { format!("::core::option::Option::None::<{}<()>>", tokens.to_string()) } else { format!("::core::option::Option::None::<{}>", tokens.to_string()) } .parse() .unwrap() } }