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