format_all_args/
lib.rs

1// Copyright (c) 2022 Vadim Glinka
2//
3// See the COPYRIGHT file at the top-level directory of this distribution
4// and at https://github.com/vglinka/format_all_args/blob/main/COPYRIGHT.
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9// option. This file may not be copied, modified, or distributed
10// except according to those terms.
11
12#[macro_export] macro_rules!
13format_all_args {
14    // 0 args
15    () => { "" };
16    // 1 arg
17    ( $arg:expr $(,)? ) => {
18        format_args!("{}", $arg)
19    };
20    // Optimization. The number of arguments is less than or equal to 10.
21    ( $a1:expr, $a2:expr $(,)? ) => {
22        format_args!("{}{}", $a1, $a2)
23    };
24    ( $a1:expr, $a2:expr, $a3:expr $(,)? ) => {
25        format_args!("{}{}{}", $a1, $a2, $a3)
26    };
27    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)? ) => {
28        format_args!("{}{}{}{}", $a1, $a2, $a3, $a4)    
29    };
30    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr $(,)? ) => {
31        format_args!("{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5)
32    };
33    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr $(,)? ) => {
34        format_args!("{}{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5, $a6)
35    };
36    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr $(,)? ) => {
37        format_args!("{}{}{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5, $a6, $a7)
38    };
39    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr $(,)? ) => {
40        format_args!("{}{}{}{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
41    };
42    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr $(,)? ) => {
43        format_args!("{}{}{}{}{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
44    };
45    ( $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr, $a10:expr $(,)? ) => {
46        format_args!("{}{}{}{}{}{}{}{}{}{}", $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10)
47    };
48    // Any number of arguments > 10.
49    // At each level of recursion, we subtract 10 arguments from
50    // the total number of arguments.
51    ( $arg_1:expr, $arg_2:expr, $arg_3:expr, $arg_4:expr, $arg_5:expr, $arg_6:expr, $arg_7:expr, $arg_8:expr, $arg_9:expr, $arg_10:expr, $($args:expr),* $(,)? ) => {        
52        format_args!("{}{}{}{}{}{}{}{}{}{}{}", $arg_1, $arg_2, $arg_3, $arg_4, $arg_5, $arg_6, $arg_7, $arg_8, $arg_9, $arg_10, format_all_args!($($args),*))
53    };
54}
55
56#[macro_export] macro_rules!
57optional_arg {
58    (           ) => { ""     };
59    ( $($a:expr)* ) => { $($a)* };
60}
61
62#[cfg(test)]
63mod tests {
64    macro_rules! check {
65        ( $test_name:tt; $($a:expr),* $(,)? ) => {
66            #[test]
67            fn $test_name() {
68                let result = format!("{}", format_all_args!($($a),*));
69                assert_eq!(result, concat!($($a),*));
70            }
71        };
72    }
73    
74    macro_rules! optional_arg_test { ( $($a:expr)? ) => { optional_arg!($($a)?) }; }
75    //                                 ----------^                      -----^
76    //                                 optional                         optional
77    
78    check!(a1; 1);
79    check!(a2; 1,2);
80    check!(a3; 1,2,3);
81    check!(a4; 1,2,3,4);
82    check!(a5; 1,2,3,4,5);
83    check!(a6; 1,2,3,4,5,6);
84    check!(a7; 1,2,3,4,5,6,7);
85    check!(a8; 1,2,3,4,5,6,7,8);
86    check!(a9; 1,2,3,4,5,6,7,8,9);
87    check!(a10; 1,2,3,4,5,6,7,8,9,10);
88    check!(long_list; 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0);
89
90
91    #[test]
92    fn no_args() {
93        let result = format!("{}", format_all_args!( ));
94        //                                          ^
95        assert_eq!(result, "");
96    }
97    
98    #[test]
99    fn no_colon() {
100        let result = format!("{}", format_all_args!(1 ));
101        //                                           ^
102        assert_eq!(result, "1");
103        
104        let result = format!("{}", format_all_args!(1,2,3,4,5 ));
105        //                                                   ^
106        assert_eq!(result, "12345");
107        
108        let result = format!("{}", format_all_args!(1,2,3,4,5,6,7,8,9,0,1,2 ));
109        //                                                                 ^
110        assert_eq!(result, "123456789012");
111        
112        let result = format!("{}", format_all_args!(optional_arg_test!(6) ));
113        //                                                               ^
114        assert_eq!(result, "6");
115    }
116    
117    #[test]
118    fn colon() {
119        let result = format!("{}", format_all_args!(1,));
120        //                                           ^
121        assert_eq!(result, "1");
122    
123        let result = format!("{}", format_all_args!(1,2,3,4,5,));
124        //                                                   ^
125        assert_eq!(result, "12345");
126        
127        let result = format!("{}", format_all_args!(1,2,3,4,5,6,7,8,9,0,1,2,));
128        //                                                                 ^
129        assert_eq!(result, "123456789012");
130        
131        let result = format!("{}", format_all_args!(optional_arg_test!(6),));
132        //                                                               ^
133        assert_eq!(result, "6");
134    }
135        
136    #[test]
137    fn optional_arg_test() {             
138        let result = format!("{}", format_all_args!(1,2,3,4,5,optional_arg_test!(6),7));
139        //                                                                       ^
140        assert_eq!(result, "1234567");
141        //                       ^
142        
143        let result = format!("{}", format_all_args!(1,2,3,4,5,6,7,8,9,0,1,2,3,optional_arg_test!(4),5));
144        //                                                                                       ^
145        assert_eq!(result, "123456789012345");
146        //                               ^
147    }
148
149    #[test]
150    fn optional_arg_test_none() {
151        let result = format!("{}", format_all_args!(1,2,3,4,5,optional_arg_test!( ),7));
152        //                                                                       ^
153        assert_eq!(result, "123457");
154        //                      ^^
155        
156        let result = format!("{}", format_all_args!(1,2,3,4,5,6,7,8,9,0,1,2,3,optional_arg_test!( ),5));
157        //                                                                                       ^
158        assert_eq!(result, "12345678901235");
159        //                              ^^
160    }
161}