const_str/__ctfe/trim_ascii.rs
1pub struct TrimAscii<T>(pub T);
2
3impl<'a> TrimAscii<&'a str> {
4 pub const fn const_eval(&self) -> &'a str {
5 crate::str::trim_ascii(self.0)
6 }
7}
8
9pub struct TrimAsciiStart<T>(pub T);
10
11impl<'a> TrimAsciiStart<&'a str> {
12 pub const fn const_eval(&self) -> &'a str {
13 crate::str::trim_ascii_start(self.0)
14 }
15}
16
17pub struct TrimAsciiEnd<T>(pub T);
18
19impl<'a> TrimAsciiEnd<&'a str> {
20 pub const fn const_eval(&self) -> &'a str {
21 crate::str::trim_ascii_end(self.0)
22 }
23}
24
25/// Trims ASCII whitespace from both ends of a string.
26///
27/// ASCII whitespace characters are space (0x20), tab (0x09), newline (0x0A),
28/// vertical tab (0x0B), form feed (0x0C), and carriage return (0x0D).
29///
30/// This macro is [const-fn compatible](./index.html#const-fn-compatible).
31///
32/// # Examples
33///
34/// ```
35/// const TRIMMED: &str = const_str::trim_ascii!(" hello world ");
36/// assert_eq!(TRIMMED, "hello world");
37///
38/// const MIXED: &str = const_str::trim_ascii!("\t\n hello\tworld\n \r");
39/// assert_eq!(MIXED, "hello\tworld");
40///
41/// const EMPTY: &str = const_str::trim_ascii!(" ");
42/// assert_eq!(EMPTY, "");
43///
44/// // Works in const functions too
45/// const fn process_string(s: &str) -> &str {
46/// const_str::trim_ascii!(s)
47/// }
48/// assert_eq!(process_string(" test "), "test");
49/// ```
50#[macro_export]
51macro_rules! trim_ascii {
52 ($s: expr) => {
53 $crate::__ctfe::TrimAscii($s).const_eval()
54 };
55}
56
57/// Trims ASCII whitespace from the start of a string.
58///
59/// ASCII whitespace characters are space (0x20), tab (0x09), newline (0x0A),
60/// vertical tab (0x0B), form feed (0x0C), and carriage return (0x0D).
61///
62/// This macro is [const-fn compatible](./index.html#const-fn-compatible).
63///
64/// # Examples
65///
66/// ```
67/// const TRIMMED: &str = const_str::trim_ascii_start!(" hello world ");
68/// assert_eq!(TRIMMED, "hello world ");
69///
70/// const MIXED: &str = const_str::trim_ascii_start!("\t\n hello\tworld");
71/// assert_eq!(MIXED, "hello\tworld");
72///
73/// const NO_WHITESPACE: &str = const_str::trim_ascii_start!("hello");
74/// assert_eq!(NO_WHITESPACE, "hello");
75///
76/// // Works in const functions too
77/// const fn process_string(s: &str) -> &str {
78/// const_str::trim_ascii_start!(s)
79/// }
80/// assert_eq!(process_string(" test"), "test");
81/// ```
82#[macro_export]
83macro_rules! trim_ascii_start {
84 ($s: expr) => {
85 $crate::__ctfe::TrimAsciiStart($s).const_eval()
86 };
87}
88
89/// Trims ASCII whitespace from the end of a string.
90///
91/// ASCII whitespace characters are space (0x20), tab (0x09), newline (0x0A),
92/// vertical tab (0x0B), form feed (0x0C), and carriage return (0x0D).
93///
94/// This macro is [const-fn compatible](./index.html#const-fn-compatible).
95///
96/// # Examples
97///
98/// ```
99/// const TRIMMED: &str = const_str::trim_ascii_end!(" hello world ");
100/// assert_eq!(TRIMMED, " hello world");
101///
102/// const MIXED: &str = const_str::trim_ascii_end!("hello\tworld\n \r");
103/// assert_eq!(MIXED, "hello\tworld");
104///
105/// const NO_WHITESPACE: &str = const_str::trim_ascii_end!("hello");
106/// assert_eq!(NO_WHITESPACE, "hello");
107///
108/// // Works in const functions too
109/// const fn process_string(s: &str) -> &str {
110/// const_str::trim_ascii_end!(s)
111/// }
112/// assert_eq!(process_string("test "), "test");
113/// ```
114#[macro_export]
115macro_rules! trim_ascii_end {
116 ($s: expr) => {
117 $crate::__ctfe::TrimAsciiEnd($s).const_eval()
118 };
119}
120
121#[cfg(test)]
122mod tests {
123 #[test]
124 fn test_trim_ascii() {
125 const S1: &str = trim_ascii!(" hello world ");
126 assert_eq!(S1, "hello world");
127
128 const S2: &str = trim_ascii!("\t\n hello\tworld\n \r");
129 assert_eq!(S2, "hello\tworld");
130
131 const S3: &str = trim_ascii!(" ");
132 assert_eq!(S3, "");
133
134 const S4: &str = trim_ascii!("hello");
135 assert_eq!(S4, "hello");
136
137 const S5: &str = trim_ascii!("");
138 assert_eq!(S5, "");
139 }
140
141 #[test]
142 fn test_trim_ascii_start() {
143 const S1: &str = trim_ascii_start!(" hello world ");
144 assert_eq!(S1, "hello world ");
145
146 const S2: &str = trim_ascii_start!("\t\n hello\tworld");
147 assert_eq!(S2, "hello\tworld");
148
149 const S3: &str = trim_ascii_start!("hello");
150 assert_eq!(S3, "hello");
151
152 const S4: &str = trim_ascii_start!("");
153 assert_eq!(S4, "");
154
155 const S5: &str = trim_ascii_start!(" ");
156 assert_eq!(S5, "");
157 }
158
159 #[test]
160 fn test_trim_ascii_end() {
161 const S1: &str = trim_ascii_end!(" hello world ");
162 assert_eq!(S1, " hello world");
163
164 const S2: &str = trim_ascii_end!("hello\tworld\n \r");
165 assert_eq!(S2, "hello\tworld");
166
167 const S3: &str = trim_ascii_end!("hello");
168 assert_eq!(S3, "hello");
169
170 const S4: &str = trim_ascii_end!("");
171 assert_eq!(S4, "");
172
173 const S5: &str = trim_ascii_end!(" ");
174 assert_eq!(S5, "");
175 }
176
177 #[test]
178 fn test_edge_cases() {
179 // Test with all types of ASCII whitespace
180 const ALL_WS: &str = trim_ascii!(" \t\n\x0B\x0C\r");
181 assert_eq!(ALL_WS, "");
182
183 // Test with whitespace in the middle (should be preserved)
184 const MIDDLE_WS: &str = trim_ascii!(" hello world ");
185 assert_eq!(MIDDLE_WS, "hello world");
186
187 // Test with only start whitespace
188 const START_WS: &str = trim_ascii!(" hello");
189 assert_eq!(START_WS, "hello");
190
191 // Test with only end whitespace
192 const END_WS: &str = trim_ascii!("hello ");
193 assert_eq!(END_WS, "hello");
194 }
195
196 #[test]
197 fn test_const_fn_compatibility() {
198 const fn process_trim(s: &str) -> &str {
199 trim_ascii!(s)
200 }
201
202 const fn process_trim_start(s: &str) -> &str {
203 trim_ascii_start!(s)
204 }
205
206 const fn process_trim_end(s: &str) -> &str {
207 trim_ascii_end!(s)
208 }
209
210 assert_eq!(process_trim(" test "), "test");
211 assert_eq!(process_trim_start(" test "), "test ");
212 assert_eq!(process_trim_end(" test "), " test");
213 }
214}