const_str/__proc/
fmt.rs

1pub use const_str_proc_macro::format_parts;
2
3/// Creates a string slice using interpolation of const expressions.
4///
5/// The input type must be one of
6///
7/// + [`&str`]
8/// + [`char`]
9/// + [`bool`]
10/// + [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`]
11/// + [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`isize`]
12///
13/// # Examples
14///
15/// ```
16/// use const_str::format as const_format;
17///
18/// const PROMPT: &str = "The answer is";
19/// const ANSWER: usize = 42;
20///
21/// const MESSAGE_1: &str = const_format!("{PROMPT} {ANSWER}");
22/// const MESSAGE_2: &str = const_format!("{} {}", PROMPT, ANSWER);
23/// const MESSAGE_3: &str = const_format!("{0} {1}", PROMPT, ANSWER);
24/// const MESSAGE_4: &str = const_format!("{a} {b}", a = PROMPT, b = ANSWER);
25/// const MESSAGE_5: &str = const_format!("{} {a}", PROMPT, a = ANSWER);
26///
27/// assert_eq!(MESSAGE_1, "The answer is 42");
28/// assert_eq!(MESSAGE_1, MESSAGE_2);
29/// assert_eq!(MESSAGE_1, MESSAGE_3);
30/// assert_eq!(MESSAGE_1, MESSAGE_4);
31/// assert_eq!(MESSAGE_1, MESSAGE_5);
32/// ```
33///
34#[cfg_attr(docsrs, doc(cfg(feature = "proc")))]
35#[macro_export]
36macro_rules! format {
37    ($fmt: literal $($args:tt)*) => {{
38        use ::core::primitive::{str, usize};
39        use $crate::__ctfe::FmtSpec;
40        #[allow(unused_imports)]
41        use $crate::{__fmt_debug, __fmt_display, __fmt_lowerhex, __fmt_upperhex, __fmt_binary};
42        const STRS: &[&str] = $crate::__proc::format_parts!($fmt $($args)*);
43        const OUTPUT_LEN: usize = $crate::__ctfe::Concat(STRS).output_len();
44        const OUTPUT_BUF: $crate::__ctfe::StrBuf<OUTPUT_LEN> = $crate::__ctfe::Concat(STRS).const_eval();
45        OUTPUT_BUF.as_str()
46    }};
47}
48
49#[cfg(test)]
50mod tests {
51    #[allow(clippy::uninlined_format_args)]
52    #[test]
53    fn test_const_format() {
54        use crate::format as const_format;
55
56        {
57            const A: usize = 1;
58            const X: &str = const_format!("{:?}", A);
59            let ans = std::format!("{:?}", A);
60            assert_eq!(X, ans);
61        }
62
63        {
64            const A: bool = true;
65            const B: bool = false;
66            const X: &str = const_format!("{1:?} {0:?} {:?}", A, B);
67            let ans = std::format!("{1:?} {0:?} {:?}", A, B);
68            assert_eq!(X, ans);
69        }
70
71        {
72            const A: char = '我';
73            const X: &str = const_format!("{a:?} {0}", A, a = A);
74            let ans = std::format!("{a:?} {0}", A, a = A);
75            assert_eq!(X, ans);
76        }
77
78        {
79            const A: &str = "团长\0\t\r\n\"'and希望之花";
80            const X: &str = const_format!("{:?}", A);
81            let ans = format!("{:?}", A);
82            assert_eq!(X, ans)
83        }
84
85        {
86            const A: u32 = 42;
87            const X: &str = const_format!("{0:x} {0:X} {0:#x} {0:#X} {0:b} {0:#b}", A);
88            let ans = std::format!("{0:x} {0:X} {0:#x} {0:#X} {0:b} {0:#b}", A);
89            assert_eq!(X, ans)
90        }
91
92        {
93            const A: i32 = -42;
94            const X: &str = const_format!("{A:x} {A:X} {A:#x} {A:#X} {A:b} {A:#b}");
95            let ans = std::format!("{0:x} {0:X} {0:#x} {0:#X} {0:b} {0:#b}", A);
96            assert_eq!(X, ans)
97        }
98    }
99}