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}