Skip to main content

tstr/
lib.rs

1//! An encoding of type-level strings, with the [`TStr`] type and related macros.
2//!
3//! This crate features all these on stable:
4//! - a relatively readable default representation of type-level strings
5//!   based on `char` const parameters.
6//! - items for converting type-level strings to `&'static str` and `&'static [u8]`
7//! - functions for comparing type-level strings to each other and `&str`
8//! - macros for asserting the (in)equality of type-level strings to each other and `&str`
9//!
10//! All of the above functionality can be used in const contexts.
11//!
12//! # Examples
13//!
14//! ### Indexing
15//!
16//! This example demonstrates how you can use type-level strings,
17//! and the [`Index`] trait, to access fields of generic types by name.
18//!
19//! ```rust
20//! use std::ops::Index;
21//!
22//! use tstr::{TS, ts};
23//!
24//! fn main(){
25//!     takes_person(&Person::new("Bob".into(), "Marley".into()));
26//!
27//!     takes_person(&OtherPerson::new("Bob", "Marley"));
28//! }
29//!
30//! fn takes_person<P>(pers: &P)
31//! where
32//!     P: Index<TS!(name), Output = str> + Index<TS!(surname), Output = str>
33//! {
34//!     assert_eq!(&pers[ts!(name)], "Bob");
35//!     assert_eq!(&pers[ts!(surname)], "Marley");
36//! }
37//!
38//!
39//! use person::Person;
40//! mod person {
41//!     use std::ops::Index;
42//!
43//!     use tstr::TS;
44//!     
45//!     pub struct Person {
46//!         name: String,
47//!         surname: String,
48//!     }
49//!     
50//!     impl Person {
51//!         pub fn new(name: String, surname: String) -> Self {
52//!             Self{name, surname}
53//!         }
54//!     }
55//!     
56//!     impl Index<TS!(name)> for Person {
57//!         type Output = str;
58//!         
59//!         fn index(&self, _: TS!(name)) -> &str {
60//!             &self.name
61//!         }
62//!     }
63//!    
64//!     impl Index<TS!(surname)> for Person {
65//!         type Output = str;
66//!         
67//!         fn index(&self, _: TS!(surname)) -> &str {
68//!             &self.surname
69//!         }
70//!     }
71//! }
72//!
73//! use other_person::OtherPerson;
74//! mod other_person {
75//!     use std::ops::Index;
76//!
77//!     use tstr::TS;
78//!     
79//!     pub struct OtherPerson {
80//!         name: &'static str,
81//!         surname: &'static str,
82//!     }
83//!     
84//!     impl OtherPerson {
85//!         pub fn new(name: &'static str, surname: &'static str) -> Self {
86//!             Self{name, surname}
87//!         }
88//!     }
89//!     
90//!     impl Index<TS!(name)> for OtherPerson {
91//!         type Output = str;
92//!         
93//!         fn index(&self, _: TS!(name)) -> &str {
94//!             self.name
95//!         }
96//!     }
97//!    
98//!     impl Index<TS!(surname)> for OtherPerson {
99//!         type Output = str;
100//!         
101//!         fn index(&self, _: TS!(surname)) -> &str {
102//!             self.surname
103//!         }
104//!     }
105//! }
106//!
107//! ```
108//!
109//! ### Type errors
110//!
111//! This example showcases what TStr looks like in simple type errors.
112//!
113//! ```rust,compile_fail
114//! let _: tstr::TS!("Hello, world!") = ();
115//! ```
116//!
117//! With no crate features enabled, the error message is this:
118//! ```text
119//! error[E0308]: mismatched types
120//!  --> tstr/src/lib.rs:114:37
121//!   |
122//! 5 | let _: tstr::TS!("Hello, world!") = ();
123//!   |        --------------------------   ^^ expected `TStr<___<..., 13>>`, found `()`
124//!   |        |
125//!   |        expected due to this
126//!   |
127//!   = note: expected struct `tstr::TStr<___<(tstr::__<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w'>, tstr::__<'o', 'r', 'l', 'd', '!'>, (), (), (), (), (), ()), 13>>`
128//!           found unit type `()`
129//! ```
130//! As you can see, the string is represented as a collection of `char` const parameters.
131//!
132//! When the `"nightly_str_generics"` feature is enabled (which requires the nightly compiler),
133//! the error message is this:
134//! ```text
135//! error[E0308]: mismatched types
136//!  --> tstr/src/lib.rs:114:37
137//!   |
138//! 5 | let _: tstr::TS!("Hello, world!") = ();
139//!   |        --------------------------   ^^ expected `TStr<___<"Hello, world!">>`, found `()`
140//!   |        |
141//!   |        expected due to this
142//!   |
143//!   = note: expected struct `tstr::TStr<___<"Hello, world!">>`
144//!           found unit type `()`
145//! ```
146//!
147//!
148//!
149//! # Macro expansion
150//!
151//! This library reserves the right to change how it represent type-level strings internally
152//! in every single release, and cargo feature combination.
153//!
154//! This only affects you if you expand the code generated by macros from this crate,
155//! and then use that expanded code instead of going through the macros.
156//!
157//! # Cargo features
158//!
159//! - `"const_panic"`(enabled by default):
160//! Enables [`const_panic`] reexports, assertion macros,
161//! and `const_panic::fmt::PanicFmt` impl for `TStr`.
162//!
163//! - `"use_syn"`(disabled by default):
164//! Changes how literals passed to the macros of this crate are parsed to use the `syn` crate.
165//! Use this if there is some literal that could not be
166//! parsed but is a valid str/integer literal.
167//!
168//! - `"serde"`(disabled by default):
169//! Enables serde dependency and implements `serde::{Serialize, Deserialize}` for `TStr`
170//!
171//! - `"str_generics"`(disabled by default):
172//! Changes the representation of type-level strings to use a `&'static str` const parameter,
173//! making for better compiler errors.
174//! As of 2025-08-18, this feature can't be enabled, because it
175//! requires `&'static str` to be stably usable as const parameters.
176//! Consider using `"nightly_str_generics"` if this feature can't be used.
177//!
178//! - `"nightly_str_generics"`(disabled by default): Equivalent to the `"str_generics"` feature,
179//! and enables the nightly compiler features to use `&'static str` const parameters.
180//!
181//! # No-std support
182//!
183//! This crate is unconditionally `#![no_std]`, and can be used anywhere that Rust can be.
184//!
185//! # Minimum Supported Rust Version
186//!
187//! This crate supports Rust versions back to Rust 1.88.0.
188//!
189//! [`TStr`]: crate::TStr
190//! [`const_panic`]: const_panic
191//! [`Index`]: core::ops::Index
192//! [`tstr::utils`]: crate::utils
193#![no_std]
194#![cfg_attr(feature = "nightly_str_generics", feature(adt_const_params))]
195#![cfg_attr(feature = "nightly_str_generics", feature(unsized_const_params))]
196#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
197#![cfg_attr(feature = "nightly_str_generics", allow(incomplete_features))]
198//////////
199// lints
200//////////
201#![allow(non_camel_case_types)]
202#![forbid(unsafe_code)]
203
204#[cfg(feature = "const_panic")]
205mod assertions;
206
207pub mod strlike;
208
209mod macros;
210mod private_macros;
211
212mod tstr_fns;
213mod tstr_trait;
214mod tstr_type;
215
216#[cfg(feature = "serde")]
217mod tstr_serde_impls;
218
219#[cfg(not(feature = "str_generics"))]
220mod tstr_impl_with_chars;
221
222#[cfg(not(feature = "str_generics"))]
223pub(crate) use tstr_impl_with_chars::__TStrRepr;
224
225#[cfg(feature = "str_generics")]
226mod tstr_impl_with_str;
227
228#[cfg(feature = "str_generics")]
229pub(crate) use tstr_impl_with_str::__TStrRepr;
230
231pub mod utils;
232
233#[doc(hidden)]
234extern crate self as tstr;
235
236#[doc(hidden)]
237pub use tstr_proc_macros::__ts_impl;
238
239use crate::tstr_trait::__TStrArgBinary;
240
241pub use crate::{
242    tstr_fns::*,
243    tstr_trait::{IsTStr, TStrArg},
244    tstr_type::TStr,
245};
246
247pub use typewit;
248
249#[doc(no_inline)]
250#[cfg(feature = "const_panic")]
251#[cfg_attr(feature = "docsrs", doc(cfg(feature = "const_panic")))]
252pub use const_panic::{self, unwrap_ok as unwrap};
253
254include! {"./p.rs"}
255
256#[doc(hidden)]
257pub mod __p {
258    pub use crate::__Empty;
259    pub use crate::macros::__IgnoreArgReturnEmpty;
260
261    #[cfg(feature = "const_panic")]
262    pub use const_panic::concat_panic;
263
264    pub use core::array;
265    pub use core::{concat, stringify};
266}