1 | /// Replaces all the instances of `$pattern` in `$input` |
2 | /// (a `&'static str` constant) with `$replace_with` (a `&'static str` constant). |
3 | /// |
4 | /// # Signature |
5 | /// |
6 | /// This macro acts like a function of this signature: |
7 | /// ```rust |
8 | /// # trait Pattern {} |
9 | /// fn str_replace( |
10 | /// input: &'static str, |
11 | /// pattern: impl Pattern, |
12 | /// replace_with: &'static str, |
13 | /// ) -> &'static str |
14 | /// # {"" } |
15 | /// ``` |
16 | /// and is evaluated at compile-time. |
17 | /// |
18 | /// Where `pattern` can be any of these types: |
19 | /// |
20 | /// - `&'static str` |
21 | /// |
22 | /// - `char` |
23 | /// |
24 | /// - `u8`: required to be ascii (`0` up to `127` inclusive). |
25 | /// |
26 | /// # Example |
27 | /// |
28 | /// |
29 | /// ```rust |
30 | /// use const_format::str_replace; |
31 | /// |
32 | /// // Passing a string pattern |
33 | /// assert_eq!( |
34 | /// str_replace!("The incredible shrinking man." , "i" , "eee" ), |
35 | /// "The eeencredeeeble shreeenkeeeng man." , |
36 | /// ); |
37 | /// |
38 | /// // Passing a char pattern |
39 | /// assert_eq!( |
40 | /// str_replace!("The incredible shrinking man." , ' ' , "---" ), |
41 | /// "The---incredible---shrinking---man." , |
42 | /// ); |
43 | /// |
44 | /// // Passing an ascii u8 pattern. |
45 | /// assert_eq!( |
46 | /// str_replace!("The incredible shrinking man." , b'i' , "eee" ), |
47 | /// "The eeencredeeeble shreeenkeeeng man." , |
48 | /// ); |
49 | /// |
50 | /// // Removing all instances of the pattern |
51 | /// assert_eq!( |
52 | /// str_replace!("remove haire" , "re" , "" ), |
53 | /// "move hai" , |
54 | /// ); |
55 | /// |
56 | /// // This shows that all the arguments can be `const`s, they don't have to be literals. |
57 | /// { |
58 | /// const IN: &str = "Foo Boo Patoo" ; |
59 | /// const REPLACING: &str = "oo" ; |
60 | /// const REPLACE_WITH: &str = "uh" ; |
61 | /// assert_eq!(str_replace!(IN, REPLACING, REPLACE_WITH), "Fuh Buh Patuh" ); |
62 | /// } |
63 | /// ``` |
64 | /// |
65 | /// [`str::replace`]: https://doc.rust-lang.org/std/primitive.str.html#method.replace |
66 | #[macro_export ] |
67 | macro_rules! str_replace { |
68 | ($input:expr, $pattern:expr, $replace_with:expr $(,)*) => { |
69 | $crate::__str_const! {{ |
70 | const ARGS_OSRCTFL4A: $crate::__str_methods::ReplaceInput = |
71 | $crate::__str_methods::ReplaceInputConv($input, $pattern, $replace_with).conv(); |
72 | |
73 | { |
74 | const OB: &[$crate::pmr::u8; ARGS_OSRCTFL4A.replace_length()] = |
75 | &ARGS_OSRCTFL4A.replace(); |
76 | |
77 | const OS: &$crate::pmr::str = unsafe { $crate::__priv_transmute_bytes_to_str!(OB) }; |
78 | |
79 | OS |
80 | } |
81 | }} |
82 | }; |
83 | } |
84 | |
85 | /// Creates a `&'static str` by repeating a `&'static str` constant `times` times |
86 | /// |
87 | /// This is evaluated at compile-time. |
88 | /// |
89 | /// # Example |
90 | /// |
91 | /// ```rust |
92 | /// use const_format::str_repeat; |
93 | /// |
94 | /// { |
95 | /// const OUT: &str = str_repeat!("hi " , 4); |
96 | /// assert_eq!(OUT, "hi hi hi hi " ) |
97 | /// } |
98 | /// { |
99 | /// const IN: &str = "bye " ; |
100 | /// const REPEAT: usize = 5; |
101 | /// const OUT: &str = str_repeat!(IN, REPEAT); |
102 | /// assert_eq!(OUT, "bye bye bye bye bye " ) |
103 | /// } |
104 | /// |
105 | /// ``` |
106 | /// |
107 | /// ### Failing |
108 | /// |
109 | /// If this macro would produce too large a string, |
110 | /// it causes a compile-time error. |
111 | /// |
112 | /// ```compile_fail |
113 | /// const_format::str_repeat!("hello" , usize::MAX / 4); |
114 | /// ``` |
115 | /// |
116 | #[cfg_attr ( |
117 | feature = "__test" , |
118 | doc = r##" |
119 | ```rust |
120 | const_format::str_repeat!("hello", usize::MAX.wrapping_add(4)); |
121 | ``` |
122 | "## |
123 | )] |
124 | #[macro_export ] |
125 | macro_rules! str_repeat { |
126 | ($string:expr, $times:expr $(,)*) => { |
127 | $crate::__str_const! {{ |
128 | const P_OSRCTFL4A: &$crate::__str_methods::StrRepeatArgs = |
129 | &$crate::__str_methods::StrRepeatArgs($string, $times); |
130 | |
131 | { |
132 | use $crate::__hidden_utils::PtrToRef; |
133 | use $crate::pmr::{str, transmute, u8}; |
134 | |
135 | const P: &$crate::__str_methods::StrRepeatArgs = P_OSRCTFL4A; |
136 | |
137 | $crate::pmr::respan_to! { |
138 | ($string) |
139 | const _ASSERT_VALID_LEN: () = P.assert_valid(); |
140 | } |
141 | |
142 | const OUT_B: &[u8; P.out_len] = &unsafe { |
143 | let ptr = P.str.as_ptr() as *const [u8; P.str_len]; |
144 | transmute::<[[u8; P.str_len]; P.repeat], [u8; P.out_len]>( |
145 | [*PtrToRef { ptr }.reff; P.repeat], |
146 | ) |
147 | }; |
148 | const OUT_S: &str = unsafe { $crate::__priv_transmute_bytes_to_str!(OUT_B) }; |
149 | OUT_S |
150 | } |
151 | }} |
152 | }; |
153 | } |
154 | |
155 | /// Replaces a substring in a `&'static str` constant. |
156 | /// Returns both the new resulting `&'static str`, and the replaced substring. |
157 | /// |
158 | /// # Alternatives |
159 | /// |
160 | /// For an alternative which only returns the string with the applied replacement, |
161 | /// you can use [`str_splice_out`]. |
162 | /// |
163 | /// # Signature |
164 | /// |
165 | /// This macro acts like a function of this signature: |
166 | /// ```rust |
167 | /// # trait SomeIndex {} |
168 | /// fn str_splice( |
169 | /// input: &'static str, |
170 | /// range: impl SomeIndex, |
171 | /// replace_with: &'static str, |
172 | /// ) -> const_format::SplicedStr |
173 | /// # {unimplemented!()} |
174 | /// ``` |
175 | /// and is evaluated at compile-time. |
176 | /// |
177 | /// ### `range` argument |
178 | /// |
179 | /// The `range` parameter determines what part of `input` is replaced, |
180 | /// and can be any of these types: |
181 | /// |
182 | /// - `usize`: the starting index of a char, only includes that char. |
183 | /// - `Range<usize>` |
184 | /// - `RangeTo<usize>` |
185 | /// - `RangeFrom<usize>` |
186 | /// - `RangeInclusive<usize>` |
187 | /// - `RangeToInclusive<usize>` |
188 | /// - `RangeFull` |
189 | /// |
190 | /// [`SplicedStr`] contains: |
191 | /// - `output`: a `&'static str` with the substring at `range` in `input` replaced with |
192 | /// `replace_with`. |
193 | /// - `removed`: the substring at `range` in `input`. |
194 | /// |
195 | /// # Example |
196 | /// |
197 | /// ```rust |
198 | /// use const_format::{str_splice, SplicedStr}; |
199 | /// |
200 | /// const OUT: SplicedStr = str_splice!("foo bar baz" , 4..=6, "is" ); |
201 | /// assert_eq!(OUT , SplicedStr{output: "foo is baz" , removed: "bar" }); |
202 | /// |
203 | /// // You can pass `const`ants to this macro, not just literals |
204 | /// { |
205 | /// const IN: &str = "this is bad" ; |
206 | /// const INDEX: std::ops::RangeFrom<usize> = 8..; |
207 | /// const REPLACE_WITH: &str = "... fine" ; |
208 | /// const OUT: SplicedStr = str_splice!(IN, INDEX, REPLACE_WITH); |
209 | /// assert_eq!(OUT , SplicedStr{output: "this is ... fine" , removed: "bad" }); |
210 | /// } |
211 | /// { |
212 | /// const OUT: SplicedStr = str_splice!("ABC豆-" , 3, "DEFGH" ); |
213 | /// assert_eq!(OUT , SplicedStr{output: "ABCDEFGH-" , removed: "豆" }); |
214 | /// } |
215 | /// ``` |
216 | /// |
217 | /// ### Invalid index |
218 | /// |
219 | /// Invalid indices cause compilation errors. |
220 | /// |
221 | /// ```compile_fail |
222 | /// const_format::str_splice!("foo" , 0..10, "" ); |
223 | /// ``` |
224 | #[cfg_attr ( |
225 | feature = "__test" , |
226 | doc = r#" |
227 | ```rust |
228 | const_format::str_splice!("foo", 0..3, ""); |
229 | ``` |
230 | |
231 | ```compile_fail |
232 | const_format::str_splice!("foo", 0..usize::MAX, ""); |
233 | ``` |
234 | |
235 | ```rust |
236 | assert_eq!( |
237 | const_format::str_splice!("効率的", 3..6, "A"), |
238 | const_format::SplicedStr{output: "効A的", removed: "率"} , |
239 | ); |
240 | ``` |
241 | |
242 | ```compile_fail |
243 | assert_eq!( |
244 | const_format::str_splice!("効率的", 1..6, "A"), |
245 | const_format::SplicedStr{output: "効A的", removed: "率"} , |
246 | ); |
247 | ``` |
248 | |
249 | ```compile_fail |
250 | assert_eq!( |
251 | const_format::str_splice!("効率的", 3..5, "A"), |
252 | const_format::SplicedStr{output: "効A的", removed: "率"} , |
253 | ); |
254 | ``` |
255 | |
256 | "# |
257 | )] |
258 | /// |
259 | /// |
260 | /// [`SplicedStr`]: ./struct.SplicedStr.html |
261 | /// [`str_splice_out`]: ./macro.str_splice_out.html |
262 | #[macro_export ] |
263 | macro_rules! str_splice { |
264 | ($string:expr, $index:expr, $insert:expr $(,)*) => { |
265 | $crate::__const! { |
266 | $crate::__str_methods::SplicedStr => |
267 | $crate::__str_splice!($string, $index, $insert) |
268 | } |
269 | }; |
270 | } |
271 | |
272 | /// Alternative version of [`str_splice`] which only returns the string |
273 | /// with the applied replacement. |
274 | /// |
275 | /// # Example |
276 | /// |
277 | /// ```rust |
278 | /// use const_format::{str_splice_out, SplicedStr}; |
279 | /// |
280 | /// const OUT: &str = str_splice_out!("foo bar baz" , 4..=6, "is" ); |
281 | /// assert_eq!(OUT , "foo is baz" ); |
282 | /// |
283 | /// // You can pass `const`ants to this macro, not just literals |
284 | /// { |
285 | /// const IN: &str = "this is bad" ; |
286 | /// const INDEX: std::ops::RangeFrom<usize> = 8..; |
287 | /// const REPLACE_WITH: &str = "... fine" ; |
288 | /// const OUT: &str = str_splice_out!(IN, INDEX, REPLACE_WITH); |
289 | /// assert_eq!(OUT , "this is ... fine" ); |
290 | /// } |
291 | /// { |
292 | /// const OUT: &str = str_splice_out!("ABC豆-" , 3, "DEFGH" ); |
293 | /// assert_eq!(OUT , "ABCDEFGH-" ); |
294 | /// } |
295 | /// ``` |
296 | /// |
297 | /// [`str_splice`]: ./macro.str_splice.html |
298 | #[macro_export ] |
299 | macro_rules! str_splice_out { |
300 | ($string:expr, $index:expr, $insert:expr $(,)*) => { |
301 | $crate::__str_const! { |
302 | $crate::__str_splice!($string, $index, $insert).output |
303 | } |
304 | }; |
305 | } |
306 | |
307 | #[doc (hidden)] |
308 | #[macro_export ] |
309 | macro_rules! __str_splice { |
310 | ($string:expr, $index:expr, $insert:expr) => {{ |
311 | const P_OSRCTFL4A: $crate::__str_methods::StrSpliceArgs = |
312 | $crate::__str_methods::StrSplceArgsConv($string, $index, $insert).conv(); |
313 | { |
314 | use $crate::__hidden_utils::PtrToRef; |
315 | use $crate::__str_methods::{DecomposedString, SplicedStr, StrSpliceArgs}; |
316 | use $crate::pmr::{str, u8}; |
317 | |
318 | const P: &StrSpliceArgs = &P_OSRCTFL4A; |
319 | |
320 | type DecompIn = |
321 | DecomposedString<[u8; P.used_rstart], [u8; P.used_rlen], [u8; P.suffix_len]>; |
322 | |
323 | type DecompOut = |
324 | DecomposedString<[u8; P.used_rstart], [u8; P.insert_len], [u8; P.suffix_len]>; |
325 | |
326 | $crate::pmr::respan_to! { |
327 | ($string) |
328 | const _ASSERT_VALID_INDEX: () = P.index_validity.assert_valid(); |
329 | } |
330 | |
331 | const OUT_A: (&DecompOut, &str) = unsafe { |
332 | let input = PtrToRef { |
333 | ptr: P.str.as_ptr() as *const DecompIn, |
334 | } |
335 | .reff; |
336 | let insert = PtrToRef { |
337 | ptr: P.insert.as_ptr() as *const [u8; P.insert_len], |
338 | } |
339 | .reff; |
340 | |
341 | ( |
342 | &DecomposedString { |
343 | prefix: input.prefix, |
344 | middle: *insert, |
345 | suffix: input.suffix, |
346 | }, |
347 | $crate::__priv_transmute_bytes_to_str!(&input.middle), |
348 | ) |
349 | }; |
350 | |
351 | const OUT: SplicedStr = unsafe { |
352 | let output = OUT_A.0 as *const DecompOut as *const [u8; P.out_len]; |
353 | SplicedStr { |
354 | output: $crate::__priv_transmute_raw_bytes_to_str!(output), |
355 | removed: OUT_A.1, |
356 | } |
357 | }; |
358 | |
359 | OUT |
360 | } |
361 | }}; |
362 | } |
363 | |
364 | /// Indexes a `&'static str` constant. |
365 | /// |
366 | /// |
367 | /// # Signature |
368 | /// |
369 | /// This macro acts like a function of this signature: |
370 | /// ```rust |
371 | /// # trait SomeIndex {} |
372 | /// fn str_index(input: &'static str, range: impl SomeIndex) -> &'static str |
373 | /// # {unimplemented!()} |
374 | /// ``` |
375 | /// and is evaluated at compile-time. |
376 | /// |
377 | /// This accepts |
378 | /// [the same `range` arguments as `str_splice`](macro.str_splice.html#range-argument) |
379 | /// |
380 | /// # Example |
381 | /// |
382 | /// ``` |
383 | /// use const_format::str_index; |
384 | /// |
385 | /// use std::ops::RangeFrom; |
386 | /// |
387 | /// assert_eq!(str_index!("foo bar baz" , ..7), "foo bar" ); |
388 | /// assert_eq!(str_index!("foo bar baz" , 4..7), "bar" ); |
389 | /// assert_eq!(str_index!("foo bar baz" , 4..), "bar baz" ); |
390 | /// |
391 | /// { |
392 | /// const IN: &str = "hello world" ; |
393 | /// const INDEX: RangeFrom<usize> = 6..; |
394 | /// // You can pass `const`ants to this macro, not just literals |
395 | /// const OUT_0: &str = str_index!(IN, INDEX); |
396 | /// assert_eq!(OUT_0, "world" ); |
397 | /// } |
398 | /// { |
399 | /// const OUT: &str = str_index!("hello world" , 4); |
400 | /// assert_eq!(OUT, "o" ); |
401 | /// } |
402 | /// |
403 | /// ``` |
404 | /// |
405 | /// ### Invalid index |
406 | /// |
407 | /// Invalid indices cause compilation errors. |
408 | /// |
409 | /// ```compile_fail |
410 | /// const_format::str_index!("foo" , 0..10); |
411 | /// ``` |
412 | #[cfg_attr ( |
413 | feature = "__test" , |
414 | doc = r#" |
415 | ```rust |
416 | assert_eq!(const_format::str_index!("効率的", 3..6), "率"); |
417 | ``` |
418 | |
419 | ```compile_fail |
420 | assert_eq!(const_format::str_index!("効率的", 3..5), "率"); |
421 | ``` |
422 | ```compile_fail |
423 | assert_eq!(const_format::str_index!("効率的", 4..6), "率"); |
424 | ``` |
425 | "# |
426 | )] |
427 | /// |
428 | /// |
429 | #[macro_export ] |
430 | macro_rules! str_index { |
431 | ($string:expr, $index:expr $(,)*) => { |
432 | $crate::__str_const! {{ |
433 | const P_OSRCTFL4A: $crate::__str_methods::StrIndexArgs = |
434 | $crate::__str_methods::StrIndexArgsConv($string, $index).conv(); |
435 | |
436 | { |
437 | $crate::pmr::respan_to! { |
438 | ($string) |
439 | const _ASSERT_VALID_INDEX: () = |
440 | P_OSRCTFL4A.index_validity.assert_valid(); |
441 | } |
442 | |
443 | use $crate::__hidden_utils::PtrToRef; |
444 | use $crate::__str_methods::DecomposedString; |
445 | type DecompIn = DecomposedString< |
446 | [u8; P_OSRCTFL4A.used_rstart], |
447 | [u8; P_OSRCTFL4A.used_rlen], |
448 | [u8; 0], |
449 | >; |
450 | |
451 | const OUT: &'static str = unsafe { |
452 | let input = PtrToRef { |
453 | ptr: P_OSRCTFL4A.str.as_ptr() as *const DecompIn, |
454 | } |
455 | .reff; |
456 | $crate::__priv_transmute_raw_bytes_to_str!(&input.middle) |
457 | }; |
458 | |
459 | OUT |
460 | } |
461 | }} |
462 | }; |
463 | } |
464 | |
465 | /// Indexes a `&'static str` constant, |
466 | /// returning `None` when the index is not on a character boundary. |
467 | /// |
468 | /// |
469 | /// # Signature |
470 | /// |
471 | /// This macro acts like a function of this signature: |
472 | /// ```rust |
473 | /// # trait SomeIndex {} |
474 | /// fn str_get(input: &'static str, range: impl SomeIndex) -> Option<&'static str> |
475 | /// # {unimplemented!()} |
476 | /// ``` |
477 | /// and is evaluated at compile-time. |
478 | /// |
479 | /// This accepts |
480 | /// [the same `range` arguments as `str_splice`](macro.str_splice.html#range-argument) |
481 | /// |
482 | /// # Example |
483 | /// |
484 | /// ``` |
485 | /// use const_format::str_get; |
486 | /// |
487 | /// use std::ops::RangeFrom; |
488 | /// |
489 | /// assert_eq!(str_get!("foo 鉄 baz" , ..7), Some("foo 鉄" )); |
490 | /// assert_eq!(str_get!("foo 鉄 baz" , 4..7), Some("鉄" )); |
491 | /// assert_eq!(str_get!("foo 鉄 baz" , 4..100), None); |
492 | /// |
493 | /// |
494 | /// { |
495 | /// const IN: &str = "hello 鉄" ; |
496 | /// const INDEX: RangeFrom<usize> = 6..; |
497 | /// // You can pass `const`ants to this macro, not just literals |
498 | /// const OUT: Option<&str> = str_get!(IN, INDEX); |
499 | /// assert_eq!(OUT, Some("鉄" )); |
500 | /// } |
501 | /// { |
502 | /// const OUT: Option<&str> = str_get!("hello 鉄" , 4); |
503 | /// assert_eq!(OUT, Some("o" )); |
504 | /// } |
505 | /// { |
506 | /// // End index not on a character boundary |
507 | /// const OUT: Option<&str> = str_get!("hello 鉄" , 0..7); |
508 | /// assert_eq!(OUT, None); |
509 | /// } |
510 | /// { |
511 | /// // Out of bounds indexing |
512 | /// const OUT: Option<&str> = str_get!("hello 鉄" , 0..1000 ); |
513 | /// assert_eq!(OUT, None); |
514 | /// } |
515 | /// |
516 | /// ``` |
517 | #[cfg_attr ( |
518 | feature = "__test" , |
519 | doc = r#" |
520 | ```rust |
521 | assert_eq!(const_format::str_get!("効率的", 3..6), Some("率")); |
522 | assert_eq!(const_format::str_get!("効率的", 3..5), None); |
523 | assert_eq!(const_format::str_get!("効率的", 4..6), None); |
524 | ``` |
525 | "# |
526 | )] |
527 | /// |
528 | #[macro_export ] |
529 | macro_rules! str_get { |
530 | ($string:expr, $index:expr $(,)*) => { |
531 | $crate::__const! { |
532 | $crate::pmr::Option<&'static $crate::pmr::str> => { |
533 | const P_OSRCTFL4A: $crate::__str_methods::StrIndexArgs = |
534 | $crate::__str_methods::StrIndexArgsConv($string, $index).conv(); |
535 | |
536 | { |
537 | use $crate::__hidden_utils::PtrToRef; |
538 | use $crate::__str_methods::DecomposedString; |
539 | type DecompIn = DecomposedString< |
540 | [u8; P_OSRCTFL4A.used_rstart], |
541 | [u8; P_OSRCTFL4A.used_rlen], |
542 | [u8; 0], |
543 | >; |
544 | |
545 | const OUT: $crate::pmr::Option<&'static $crate::pmr::str> = unsafe { |
546 | if P_OSRCTFL4A.index_validity.is_valid() { |
547 | let input = PtrToRef { |
548 | ptr: P_OSRCTFL4A.str.as_ptr() as *const DecompIn, |
549 | } |
550 | .reff; |
551 | |
552 | $crate::pmr::Some($crate::__priv_transmute_raw_bytes_to_str!(&input.middle)) |
553 | } else { |
554 | $crate::pmr::None |
555 | } |
556 | }; |
557 | |
558 | OUT |
559 | } |
560 | }} |
561 | }; |
562 | } |
563 | |
564 | /// Splits `$string` (a `&'static str` constant) with `$splitter`, |
565 | /// returning an array of `&'static str`s. |
566 | /// |
567 | /// # Alternatives |
568 | /// |
569 | /// For an alternative macro which will be usable in slice patterns |
570 | /// (once [`inline_const_pat`] is stabilized) |
571 | /// you can use [`str_split_pat`]. |
572 | /// |
573 | /// # Signature |
574 | /// |
575 | /// This macro acts like a function of this signature: |
576 | /// ```rust |
577 | /// # const LEN: usize = 0; |
578 | /// # trait Splitter {} |
579 | /// fn str_split(string: &'static str, splitter: impl Splitter) -> [&'static str; LEN] |
580 | /// # { [] } |
581 | /// ``` |
582 | /// and is evaluated at compile-time. |
583 | /// |
584 | /// `impl Splitter` is any of these types: |
585 | /// |
586 | /// - `&'static str` |
587 | /// |
588 | /// - `char` |
589 | /// |
590 | /// - `u8`: only ascii values (0 up to 127 inclusive) are allowed |
591 | /// |
592 | /// The value of `LEN` depends on the `string` and `splitter` arguments. |
593 | /// |
594 | /// |
595 | /// # Example |
596 | /// |
597 | /// ```rust |
598 | /// use const_format::str_split; |
599 | /// |
600 | /// assert_eq!(str_split!("this is nice", ' '), ["this", "is", "nice"]); |
601 | /// |
602 | /// assert_eq!(str_split!("Hello, world!", ", "), ["Hello", "world!"]); |
603 | /// |
604 | /// // A `""` splitter outputs all chars individually (`str::split` does the same) |
605 | /// assert_eq!(str_split!("🧡BAR🧠", ""), ["", "🧡", "B", "A", "R", "🧠", ""]); |
606 | /// |
607 | /// // Splitting the string with an ascii byte |
608 | /// assert_eq!(str_split!("dash-separated-string", b'-'), ["dash", "separated", "string"]); |
609 | /// |
610 | /// { |
611 | /// const STR: &str = "foo bar baz"; |
612 | /// const SPLITTER: &str = " "; |
613 | /// |
614 | /// // both arguments to the `str_aplit` macro can be non-literal constants |
615 | /// const SPLIT: [&str; 3] = str_split!(STR, SPLITTER); |
616 | /// |
617 | /// assert_eq!(SPLIT, ["foo", "bar", "baz"]); |
618 | /// } |
619 | /// |
620 | /// ``` |
621 | /// |
622 | /// [`inline_const_pat`]: https://doc.rust-lang.org/1.83.0/unstable-book/language-features/inline-const-pat.html |
623 | /// [`str_split_pat`]: crate::str_split_pat |
624 | #[macro_export ] |
625 | #[cfg (feature = "rust_1_64" )] |
626 | #[cfg_attr (feature = "__docsrs" , doc(cfg(feature = "rust_1_64" )))] |
627 | macro_rules! str_split { |
628 | ($string:expr, $splitter:expr $(,)?) => {{ |
629 | const ARGS_OSRCTFL4A: $crate::__str_methods::SplitInput = |
630 | $crate::__str_methods::SplitInputConv($string, $splitter).conv(); |
631 | |
632 | { |
633 | const OB: [&$crate::pmr::str; ARGS_OSRCTFL4A.length()] = ARGS_OSRCTFL4A.split_it(); |
634 | OB |
635 | } |
636 | }}; |
637 | } |
638 | |
639 | /// Version of [`str_split`] which evaluates to a `&'static [&'static str]`. |
640 | /// |
641 | /// # Example |
642 | /// |
643 | /// Using the currently unstable [`inline_const_pat`] feature to use this macro in patterns: |
644 | /// |
645 | /// ```rust |
646 | /// # /* |
647 | /// #![feature(inline_const_pat)] |
648 | /// # */ |
649 | /// |
650 | /// use const_format::str_split_pat; |
651 | /// |
652 | /// assert!(is_it(&["foo", "bar", "baz"])); |
653 | /// assert!(!is_it(&["foo", "bar"])); |
654 | /// |
655 | /// fn is_it(slice: &[&str]) -> bool { |
656 | /// const SEP: char = ' '; |
657 | /// # /* |
658 | /// matches!(slice, str_split_pat!("foo bar baz", SEP)) |
659 | /// # */ |
660 | /// # slice == str_split_pat!("foo bar baz", SEP) |
661 | /// } |
662 | /// ``` |
663 | /// |
664 | /// [`inline_const_pat`]: https://doc.rust-lang.org/1.83.0/unstable-book/language-features/inline-const-pat.html |
665 | #[macro_export ] |
666 | #[cfg (feature = "rust_1_64" )] |
667 | #[cfg_attr (feature = "__docsrs" , doc(cfg(feature = "rust_1_64" )))] |
668 | macro_rules! str_split_pat { |
669 | ($string:expr, $splitter:expr $(,)?) => { |
670 | $crate::__const! {&'static [&'static $crate::pmr::str] => { |
671 | const ARGS_OSRCTFL4A: $crate::__str_methods::SplitInput = |
672 | $crate::__str_methods::SplitInputConv($string, $splitter).conv(); |
673 | |
674 | { |
675 | const OB: [&$crate::pmr::str; ARGS_OSRCTFL4A.length()] = ARGS_OSRCTFL4A.split_it(); |
676 | &OB |
677 | } |
678 | }} |
679 | }; |
680 | } |
681 | |