const_str/
lib.rs

1//! Compile-time string operations.
2//! See the [macro list](#macros) for what you need.
3//!
4//! ## MSRV history
5//!
6//! Current: Rust 1.77.0
7//!
8//! - `v1.0.0`: Rust 1.77.0
9//! - `v0.7.0`: Rust 1.77.0
10//! - `v0.6.0`: Rust 1.77.0
11//! - `v0.5.7`: Rust 1.65.0
12//! - `v0.5.0`: Rust 1.64.0
13//! - `v0.4.0`: Rust 1.61.0
14//!
15//! ## Troubleshoot
16//!
17//! You don't have to care about this section
18//! unless you come across some compile errors about const evaluation.
19//!
20//! ```txt
21//! error[E0435]: attempt to use a non-constant value in a constant
22//! ```
23//!
24//! There are mainly two kinds of macros in this crate,
25//! which have different requirements for the arguments.
26//! - [const-context only](#const-context-only)
27//! - [const-fn compatible](#const-fn-compatible)
28//!
29//! ### const-context only
30//!
31//! These macros can only be used in [const contexts][const-context].
32//! The expanded code is equivalent to compute new [constant items][const-item].
33//! It implies that the *arguments* of these macros must be constant values,
34//! similar to [`consteval`][consteval] in C++ world.
35//!
36//! The following examples will not work:
37//! ```compile_fail
38//! const fn foo(a: &str, b: &str) -> &str {
39//!    const_str::concat!(a, b)
40//! }
41//! ```
42//! ```compile_fail
43//! const C: &str = {
44//!     let a = "Hello";
45//!     let b = "World";
46//!     const_str::concat!(a, b);
47//! };
48//! ```
49//!
50//! Instead, this way will work:
51//! ```
52//! const A: &str = "Hello";
53//! const B: &str = "World";
54//! const C: &str = const_str::concat!(A, " ", B);
55//! assert_eq!(C, "Hello World");
56//! ```
57//!
58//! ### const-fn compatible
59//!
60//! These macros can be used in [const contexts][const-context] and [const functions][const-fn].
61//! The expanded code is equivalent to calling const functions.
62//! It implies that the *arguments* of these macros can be any expressions,
63//! similar to [`constexpr`][constexpr] in C++ world.
64//!
65//! ```
66//! const fn calc(y: &str, m: &str, d: &str) -> u64 {
67//!     let y = const_str::parse!(y, u64);
68//!     let m = const_str::parse!(m, u64);
69//!     let d = const_str::parse!(d, u64);
70//!     (y * 10000 + m * 100 + d)
71//! }
72//! const TIME: u64 = calc("2025", "01", "26");
73//! assert_eq!(TIME, 20250126);
74//! ```
75//!
76//! You can also use these macros in normal functions,
77//! but they may be much slower than the runtime equivalents.
78//! It's recommended to use them only if you need compile-time evaluation.
79//!
80//! [const-context]: https://doc.rust-lang.org/reference/const_eval.html#const-context
81//! [const-fn]: https://doc.rust-lang.org/reference/const_eval.html#const-functions
82//! [const-item]: https://doc.rust-lang.org/reference/items/constant-items.html
83//! [consteval]: https://en.cppreference.com/w/cpp/language/consteval
84//! [constexpr]: https://en.cppreference.com/w/cpp/language/constexpr
85//!
86#![deny(unsafe_code, missing_docs, clippy::all, clippy::cargo)]
87#![allow(
88    clippy::missing_docs_in_private_items,
89    clippy::missing_inline_in_public_items,
90    clippy::implicit_return
91)]
92#![cfg_attr(not(any(test, feature = "std")), no_std)]
93#![cfg_attr(docsrs, feature(doc_cfg))]
94#![cfg_attr(feature = "unstable", allow(clippy::incompatible_msrv))]
95
96#[allow(unused_macros)]
97macro_rules! cfg_group {
98    ($($item:item)*) => {
99        $($item)*
100    }
101}
102
103mod ascii;
104mod bytes;
105mod printable;
106mod slice;
107mod str;
108mod utf16;
109mod utf8;
110
111#[doc(hidden)]
112#[cfg(feature = "proc")]
113pub mod __proc {
114    mod case;
115    pub use self::case::*;
116
117    mod fmt;
118    pub use self::fmt::*;
119
120    #[cfg(feature = "http")]
121    cfg_group! {
122        mod http;
123        pub use self::http::*;
124    }
125
126    #[cfg(feature = "regex")]
127    cfg_group! {
128        mod regex;
129        pub use self::regex::*;
130    }
131}
132
133#[doc(hidden)]
134pub mod __ctfe {
135    mod ascii_case;
136    pub use self::ascii_case::*;
137
138    mod chain;
139    // pub use self::chain::*;
140
141    mod compare;
142    pub use self::compare::*;
143
144    mod concat;
145    pub use self::concat::*;
146
147    mod concat_bytes;
148    pub use self::concat_bytes::*;
149
150    mod cstr;
151    pub use self::cstr::*;
152
153    mod encode;
154    pub use self::encode::*;
155
156    mod equal;
157    pub use self::equal::*;
158
159    mod find;
160    pub use self::find::*;
161
162    mod fmt;
163    pub use self::fmt::*;
164
165    mod hex;
166    pub use self::hex::*;
167
168    mod net;
169    pub use self::net::*;
170
171    mod parse;
172    pub use self::parse::*;
173
174    mod repeat;
175    pub use self::repeat::*;
176
177    mod replace;
178    pub use self::replace::*;
179
180    mod str;
181    pub use self::str::*;
182
183    mod to_byte_array;
184    pub use self::to_byte_array::*;
185
186    mod to_char_array;
187    pub use self::to_char_array::*;
188
189    mod to_str;
190    pub use self::to_str::*;
191
192    mod sorted;
193    pub use self::sorted::*;
194
195    mod split;
196    pub use self::split::*;
197
198    mod squish;
199    pub use self::squish::*;
200
201    mod is_ascii;
202    pub use self::is_ascii::*;
203
204    mod eq_ignore_ascii_case;
205    pub use self::eq_ignore_ascii_case::*;
206
207    mod unwrap;
208    pub use self::unwrap::*;
209
210    mod trim_ascii;
211    pub use self::trim_ascii::*;
212}