concat_with/
lib.rs

1/*!
2# Concat-With
3
4While the `concat!` macro in `std` is useful to create a static string slice (`&'static str`) from literals, it cannot set a separator for those. This crate therefore provides another `concat!` macro to deal with that situation.
5
6```rust
7assert_eq!("test10btrue", concat_with::concat!("test", 10, 'b', true));
8assert_eq!("test, 10, b, true", concat_with::concat!(with ", ", "test", 10, 'b', true));
9assert_eq!("test\n10\nb\ntrue", concat_with::concat_line!("test", 10, 'b', true));
10```
11
12Prefixes and suffixes can also be added.
13
14```rust
15assert_eq!("Someone says: Hello.\nSomeone says: Nice to meet you!", concat_with::concat_line!(prefix "Someone says: ", "Hello.", "Nice to meet you!"));
16```
17
18## Create Your Own Macros
19
20The `concat_impl!` macro can be used to create your own macros like `concat_line!` which concatenates literals separated by a specific literal.
21
22```rust
23#[doc(hidden)]
24pub use concat_with::{concat, concat_impl}; // re-export `concat!` and `concat_impl!` if your custom macros use `#[macro_export]`
25
26concat_impl! {
27    #[macro_export]
28    /// Concatenates literals into a static string slice separated by a comma, `,`. Prefixes and suffixes can also be added.
29    concat_with_comma => ", ",
30    #[macro_export]
31    /// Concatenates literals into a static string slice separated by a colon, `:`. Prefixes and suffixes can also be added.
32    concat_with_colon => ':',
33}
34
35assert_eq!("test, 10, b, true", concat_with_comma!("test", 10, 'b', true));
36assert_eq!("test:10:b:true", concat_with_colon!("test", 10, 'b', true));
37```
38*/
39
40#![no_std]
41
42/**
43Concatenates literals into a static string slice.
44
45This macro is like the `concat!` macro in `std`, but can also be used to concatenate literals separated by a specific literal. Prefixes and suffixes can also be added.
46
47```rust
48assert_eq!("test10btrue", concat_with::concat!("test", 10, 'b', true));
49assert_eq!("test, 10, b, true", concat_with::concat!(with ", ", "test", 10, 'b', true));
50assert_eq!("test\n10\nb\ntrue", concat_with::concat_line!("test", 10, 'b', true));
51```
52*/
53#[macro_export]
54macro_rules! concat {
55    ($(,)*) => {
56        ""
57    };
58    ( $e:expr $(,)*) => {
59        ::core::concat!($e)
60    };
61    ( $e:expr $(, $es:expr)+ $(,)*) => {
62        ::core::concat!( $e $(, $es)+ )
63    };
64    (with $w:expr $(,)*) => {
65        ""
66    };
67    (with $w:expr, $e:expr $(,)*) => {
68        ::core::concat!($e)
69    };
70    (with $w:expr, $e:expr $(, $es:expr)+ $(,)*) => {
71        ::core::concat!( $e $(, $w, $es)+ )
72    };
73    (prefix $p:expr $(,)*) => {
74        ""
75    };
76    (prefix $p:expr, $e:expr $(,)*) => {
77        ::core::concat!($p, $e)
78    };
79    (prefix $p:expr, $e:expr $(, $es:expr)+ $(,)*) => {
80        ::core::concat!($p, $e $(, $p, $es)+ )
81    };
82    (suffix $s:expr $(,)*) => {
83        ""
84    };
85    (suffix $s:expr, $e:expr $(,)*) => {
86        ::core::concat!($e, $s)
87    };
88    (suffix $s:expr, $e:expr $(, $es:expr)+ $(,)*) => {
89        ::core::concat!($e, $s $(, $es, $s)+ )
90    };
91    (prefix $p:expr, suffix $s:expr $(,)*) => {
92        ""
93    };
94    (prefix $p:expr, suffix $s:expr, $e:expr $(,)*) => {
95        ::core::concat!($p, $e, $s)
96    };
97    (prefix $p:expr, suffix $s:expr, $e:expr $(, $es:expr)+ $(,)*) => {
98        ::core::concat!($p, $e, $s $(, $p, $es, $s)+ )
99    };
100    (suffix $s:expr, prefix $p:expr $(,)*) => {
101        $crate::concat!(prefix $p, suffix $s)
102    };
103    (suffix $s:expr, prefix $p:expr, $e:expr $(,)*) => {
104        $crate::concat!(prefix $p, suffix $s, $e)
105    };
106    (suffix $s:expr, prefix $p:expr, $e:expr $(, $es:expr)+ $(,)*) => {
107        $crate::concat!(prefix $p, suffix $s, $e $(, $es)+)
108    };
109    (with $w:expr, prefix $p:expr $(,)*) => {
110        ""
111    };
112    (with $w:expr, prefix $p:expr, $e:expr $(,)*) => {
113        ::core::concat!($p, $e)
114    };
115    (with $w:expr, prefix $p:expr, $e:expr $(, $es:expr)+ $(,)*) => {
116        ::core::concat!($p, $e $(, $w, $p, $es)+ )
117    };
118    (prefix $p:expr, with $w:expr $(,)*) => {
119        $crate::concat!(with $w, prefix $p)
120    };
121    (prefix $p:expr, with $w:expr, $e:expr $(,)*) => {
122        $crate::concat!(with $w, prefix $p, $e)
123    };
124    (prefix $p:expr, with $w:expr, $e:expr $(, $es:expr)+ $(,)*) => {
125        $crate::concat!(with $w, prefix $p, $e $(, $es)+)
126    };
127    (with $w:expr, suffix $s:expr $(,)*) => {
128        ""
129    };
130    (with $w:expr, suffix $s:expr, $e:expr $(,)*) => {
131        ::core::concat!($e, $s)
132    };
133    (with $w:expr, suffix $s:expr, $e:expr $(, $es:expr)+ $(,)*) => {
134        ::core::concat!($e, $s $(, $w, $es, $s)+ )
135    };
136    (suffix $s:expr, with $w:expr $(,)*) => {
137        $crate::concat!(with $w, suffix $s)
138    };
139    (suffix $s:expr, with $w:expr, $e:expr $(,)*) => {
140        $crate::concat!(with $w, suffix $s, $e)
141    };
142    (suffix $s:expr, with $w:expr, $e:expr $(, $es:expr)+ $(,)*) => {
143        $crate::concat!(with $w, suffix $s, $e $(, $es)+)
144    };
145    (with $w:expr, prefix $p:expr, suffix $s:expr $(,)*) => {
146        ""
147    };
148    (with $w:expr, prefix $p:expr, suffix $s:expr, $e:expr $(,)*) => {
149        ::core::concat!($p, $e, $s)
150    };
151    (with $w:expr, prefix $p:expr, suffix $s:expr, $e:expr $(, $es:expr)+ $(,)*) => {
152        ::core::concat!($p, $e, $s $(, $w, $p, $es, $s)+ )
153    };
154    (prefix $p:expr, with $w:expr, suffix $s:expr $(,)*) => {
155        $crate::concat!(with $w, prefix $p, suffix $s)
156    };
157    (prefix $p:expr, with $w:expr, suffix $s:expr, $e:expr $(,)*) => {
158        $crate::concat!(with $w, prefix $p, suffix $s, $e)
159    };
160    (prefix $p:expr, with $w:expr, suffix $s:expr, $e:expr $(, $es:expr)+ $(,)*) => {
161        $crate::concat!(with $w, prefix $p, suffix $s, $e $(, $es)+)
162    };
163    (prefix $p:expr, suffix $s:expr, with $w:expr $(,)*) => {
164        $crate::concat!(with $w, prefix $p, suffix $s)
165    };
166    (prefix $p:expr, suffix $s:expr, with $w:expr, $e:expr $(,)*) => {
167        $crate::concat!(with $w, prefix $p, suffix $s, $e)
168    };
169    (prefix $p:expr, suffix $s:expr, with $w:expr, $e:expr $(, $es:expr)+ $(,)*) => {
170        $crate::concat!(with $w, prefix $p, suffix $s, $e $(, $es)+)
171    };
172    (with $w:expr, suffix $s:expr, prefix $p:expr $(,)*) => {
173        $crate::concat!(with $w, prefix $p, suffix $s)
174    };
175    (with $w:expr, suffix $s:expr, prefix $p:expr, $e:expr $(,)*) => {
176        $crate::concat!(with $w, prefix $p, suffix $s, $e)
177    };
178    (with $w:expr, suffix $s:expr, prefix $p:expr, $e:expr $(, $es:expr)+ $(,)*) => {
179        $crate::concat!(with $w, prefix $p, suffix $s, $e $(, $es)+)
180    };
181    (suffix $s:expr, with $w:expr, prefix $p:expr $(,)*) => {
182        $crate::concat!(with $w, prefix $p, suffix $s)
183    };
184    (suffix $s:expr, with $w:expr, prefix $p:expr, $e:expr $(,)*) => {
185        $crate::concat!(with $w, prefix $p, suffix $s, $e)
186    };
187    (suffix $s:expr, with $w:expr, prefix $p:expr, $e:expr $(, $es:expr)+ $(,)*) => {
188        $crate::concat!(with $w, prefix $p, suffix $s, $e $(, $es)+)
189    };
190    (suffix $s:expr, prefix $p:expr, with $w:expr $(,)*) => {
191        $crate::concat!(with $w, prefix $p, suffix $s)
192    };
193    (suffix $s:expr, prefix $p:expr, with $w:expr, $e:expr $(,)*) => {
194        $crate::concat!(with $w, prefix $p, suffix $s, $e)
195    };
196    (suffix $s:expr, prefix $p:expr, with $w:expr, $e:expr $(, $es:expr)+ $(,)*) => {
197        $crate::concat!(with $w, prefix $p, suffix $s, $e $(, $es)+)
198    };
199}
200
201/**
202Create macros used for concatenating literals separated by a specific literal.
203
204```rust
205concat_with::concat_impl! {
206    #[macro_export]
207    /// Concatenates literals into a static string slice separated by a comma and a whitespace, `, `. Prefixes and suffixes can also be added.
208    concat_with_comma => ", ",
209    #[macro_export]
210    /// Concatenates literals into a static string slice separated by a colon, `:`. Prefixes and suffixes can also be added.
211    concat_with_colon => ':',
212}
213
214assert_eq!("test, 10, b, true", concat_with_comma!("test", 10, 'b', true));
215assert_eq!("test:10:b:true", concat_with_colon!("test", 10, 'b', true));
216```
217*/
218#[macro_export]
219macro_rules! concat_impl {
220    (@inner $(#[$attr:meta])* $name:ident, $w: expr, $dollar:tt) => {
221        $(#[$attr])*
222        macro_rules! $name {
223            ($dollar($dollar e:expr),* $dollar(,)*) => {
224                $crate::concat!(with $w $dollar(, $dollar e)*)
225            };
226            (prefix $dollar p:expr $dollar(, $dollar e:expr)* $dollar(,)*) => {
227                $crate::concat!(with $w, prefix $dollar p $dollar (, $dollar e)*)
228            };
229            (suffix $dollar s:expr $dollar(, $e:expr)* $dollar(,)*) => {
230                $crate::concat!(with $w, suffix $dollar s $dollar(, $dollar e)*)
231            };
232            (prefix $dollar p:expr, suffix $dollar s:expr $dollar(, $dollar e:expr)* $dollar(,)*) => {
233                $crate::concat!(with $w, prefix $dollar p, suffix $dollar s $dollar(, $dollar e)*)
234            };
235            (suffix $dollar s:expr, prefix $dollar p:expr $dollar(, $dollar e:expr)* $dollar(,)*) => {
236                $crate::concat!(with $w, prefix $dollar p, suffix $dollar s $dollar(, $dollar e)*)
237            };
238        }
239    };
240    ($($(#[$attr:meta])* $name:ident => $w:expr),* $(,) *) => {
241        $(
242            $crate::concat_impl!(@inner $(#[$attr])* $name, $w, $);
243        )*
244    };
245}
246
247concat_impl! {
248    #[macro_export]
249    /// Concatenates literals into a static string slice separated by a line break, `\n`. Prefixes and suffixes can also be added.
250    ///
251    /// ```rust
252    /// assert_eq!("test\n10\nb\ntrue", concat_with::concat_line!("test", 10, 'b', true));
253    /// ```
254    /// */
255    concat_line => "\n"
256}