default_params/
lib.rs

1#![no_std]
2//#![feature(adt_const_params)]
3#![warn(clippy::pedantic,clippy::cargo,clippy::nursery,clippy::complexity,clippy::perf,clippy::correctness,clippy::all)]
4#![warn(clippy::cognitive_complexity,clippy::large_const_arrays)]
5#![warn(clippy::style,clippy::suspicious,large_assignments)]
6#![warn(rustdoc::all,missing_docs,clippy::empty_docs)]
7//! Do you want default function arguments or method parameters inside Rust?
8//! 
9//! Well, too bad! As this feature is currently not supported in Rust we can
10//! only emulate this functionality through macros and even more macros.
11//! 
12//! # Formalisation
13//! Default parameters could be easily formalised as
14//! ```ignore
15//! struct DefaultParam<T, const VAL: T>(T);
16//! ```
17//! 
18//! # Reality
19//! This approach however falls apart in a spectacular fashion as Rust doesn't
20//! support types dependent on other types.
21//! 
22//! Sadly this leaves us no choice. We can currently only make default arguments
23//! for `integer`, `bool` and `char` types.
24//! 
25//! # How does this implementation work?
26//! - All supported types have a wrapper around them (`i32 -> Di32`, `bool -> Dbool` ...)
27//! - Empty default arguments can be created via 
28//! ```
29//! # use default_params::Di32;
30//! let def1=Di32::<23>::new(); // Its value will be 23
31//! ```
32//! - Default arguments with values can be created via
33//! ```
34//! # use default_params::Di32;
35//! let def2=Di32::<5>::from(53); // Its value will be 53
36//! ```
37//! - The value of default arguments can be unwrapped via
38//! ```
39//! # use default_params::Di32;
40//! # let def1=Di32::<23>::new();
41//! # let def2=Di32::<5>::from(53);
42//! assert_eq!(def1.unwrap(),23);
43//! assert_eq!(def2.unwrap(),53);
44//! ```
45
46/// Trait for classifying default parameters
47pub trait DefaultParam<T> : From<T> + Default {
48    /// Unwrap a default parameter into a primitive value
49    /// 
50    /// # Example
51    /// ```
52    /// # use default_params::Di32;
53    /// let def=Di32::<23>::new();
54    /// assert_eq!(def.unwrap(),23)
55    /// ```
56    #[must_use]
57    fn unwrap(self) -> T;
58    /// Create a new Default parameter
59    /// 
60    /// # Example
61    /// ```
62    /// # use default_params::Di32;
63    /// let def=Di32::<23>::new();
64    /// assert_eq!(def.unwrap(),23)
65    /// ```
66    #[must_use]
67    fn new() -> Self;
68}
69
70macro_rules! gen_default_param {
71    ($name:ident, $type:ty) => {
72        /// Default parameter for primitive type
73        pub struct $name<const VAL: $type>(pub $type);
74
75        impl<const VAL: $type> $name<VAL> {
76            /// Unwrap a default parameter into a primitive value
77            /// 
78            /// # Example
79            /// ```
80            /// # use default_params::Di32;
81            /// let def=Di32::<23>::new();
82            /// assert_eq!(def.unwrap(),23)
83            /// ```
84            #[must_use]
85            pub const fn const_unwrap(self) -> $type {
86                self.0
87            }
88            /// Create a new Default parameter
89            /// 
90            /// # Example
91            /// ```
92            /// # use default_params::Di32;
93            /// let def=Di32::<23>::new();
94            /// assert_eq!(def.unwrap(),23)
95            /// ```
96            #[must_use]
97            pub const fn const_new() -> Self {
98                Self(VAL)
99            }
100        }
101        impl<const VAL: $type> DefaultParam<$type> for $name<VAL> {
102            fn unwrap(self) -> $type {
103                self.0
104            }
105            fn new() -> Self {
106                Self(VAL)
107            }
108        }
109        impl<const VAL: $type> From<$type> for $name<VAL> {
110            fn from(value: $type) -> Self {
111                Self(value)
112            }
113        }
114        impl<const VAL: $type> Default for $name<VAL> {
115            fn default() -> Self {
116                Self::new()
117            }
118        }
119    };
120}
121
122gen_default_param!(Di8,i8);
123gen_default_param!(Di16,i16);
124gen_default_param!(Di32,i32);
125gen_default_param!(Di64,i64);
126gen_default_param!(Di128,i128);
127gen_default_param!(Disize,isize);
128gen_default_param!(Du8,u8);
129gen_default_param!(Du16,u16);
130gen_default_param!(Du32,u32);
131gen_default_param!(Du64,u64);
132gen_default_param!(Du128,u128);
133gen_default_param!(Dusize,usize);
134gen_default_param!(Dbool,bool);
135gen_default_param!(Dchar,char);