| 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 | |