tstr/lib.rs
1//! This crate provides an encoding of type-level strings as types.
2//!
3//! # Examples
4//!
5//! ### Indexing
6//!
7//! This example demonstrates how you can use type-level strings,
8//! and the [`Index`] trait, to access fields of generic types by name.
9//!
10//! ```
11//! use std::ops::Index;
12//!
13//! use tstr::{TS, ts};
14//!
15//! fn main(){
16//! takes_person(&Person::new("Bob".into(), "Marley".into()));
17//!
18//! takes_person(&OtherPerson::new("Bob", "Marley"));
19//! }
20//!
21//! fn takes_person<P>(pers: &P)
22//! where
23//! P: Index<TS!(name), Output = str> + Index<TS!(surname), Output = str>
24//! {
25//! assert_eq!(&pers[ts!(name)], "Bob");
26//! assert_eq!(&pers[ts!(surname)], "Marley");
27//! }
28//!
29//!
30//! use person::Person;
31//! mod person {
32//! use std::ops::Index;
33//!
34//! use tstr::TS;
35//!
36//! pub struct Person {
37//! name: String,
38//! surname: String,
39//! }
40//!
41//! impl Person {
42//! pub fn new(name: String, surname: String) -> Self {
43//! Self{name, surname}
44//! }
45//! }
46//!
47//! impl Index<TS!(name)> for Person {
48//! type Output = str;
49//!
50//! fn index(&self, _: TS!(name)) -> &str {
51//! &self.name
52//! }
53//! }
54//!
55//! impl Index<TS!(surname)> for Person {
56//! type Output = str;
57//!
58//! fn index(&self, _: TS!(surname)) -> &str {
59//! &self.surname
60//! }
61//! }
62//! }
63//!
64//! use other_person::OtherPerson;
65//! mod other_person {
66//! use std::ops::Index;
67//!
68//! use tstr::TS;
69//!
70//! pub struct OtherPerson {
71//! name: &'static str,
72//! surname: &'static str,
73//! }
74//!
75//! impl OtherPerson {
76//! pub fn new(name: &'static str, surname: &'static str) -> Self {
77//! Self{name, surname}
78//! }
79//! }
80//!
81//! impl Index<TS!(name)> for OtherPerson {
82//! type Output = str;
83//!
84//! fn index(&self, _: TS!(name)) -> &str {
85//! self.name
86//! }
87//! }
88//!
89//! impl Index<TS!(surname)> for OtherPerson {
90//! type Output = str;
91//!
92//! fn index(&self, _: TS!(surname)) -> &str {
93//! self.surname
94//! }
95//! }
96//! }
97//!
98//! ```
99//!
100//! # Macro expansion
101//!
102//! This library reserves the right to change how it represent type-level strings internally
103//! in every single release, and cargo feature combination.
104//!
105//! This only affects you if you expand the code generated by macros from this crate,
106//! and then use that expanded code instead of going through the macros.
107//!
108//! # Cargo features
109//!
110//! - `"rust_1_46"`:
111//! Enables const functions in [`tstr::utils`] for comparing `&str` and `&[u8]`.
112//!
113//! - `"cmp_traits"`: Enables the traits for comparing type-level strings.
114//!
115//! - `"use_syn"`:
116//! Changes how literals passed to the macros of this crate are parsed to use the `syn` crate.
117//! Use this if there is some literal that could not be
118//! parsed but is a valid str/integer literal.
119//!
120//! - `"min_const_generics"`:
121//! changes the representation of type-level strings to use many `char` const parameter,
122//! making for better compiler errors for non-alphanumeric-ascii strings.
123//! Requires Rust 1.51.0.
124//!
125//! - `"const_generics"`:
126//! Changes the representation of type-level strings to use a `&'static str` const parameter,
127//! making for better compiler errors, and a few more features.
128//! As of 2023-03-17, this feature can't be enabled, because it
129//! requires `&'static str` to be stably usable as const parameters.
130//! Consider using `"nightly_const_generics"` if this feature can't be used.
131//!
132//! - `"nightly_const_generics"`: Equivalent to the `"const_generics"` feature,
133//! and enables the nightly compiler features to use `&'static str` const parameters.//!
134//!
135//! - `"for_examples"`: Enables the `for_examples` module,
136//! with a few types used in documentation examples.
137//!
138//! # No-std support
139//!
140//! This crate is unconditionally `#![no_std]`, and can be used anywhere that Rust can be.
141//!
142//! # Minimum Supported Rust Version
143//!
144//! This crate supports Rust versions back to Rust 1.40.0.
145//!
146//! [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html
147//! [`tstr::utils`]: ./utils/index.html
148#![no_std]
149#![cfg_attr(feature = "nightly_const_generics", feature(adt_const_params))]
150#![cfg_attr(feature = "docsrs", feature(doc_cfg, doc_auto_cfg))]
151#![allow(non_camel_case_types)]
152#![cfg_attr(feature = "nightly_const_generics", allow(incomplete_features))]
153
154#[cfg(feature = "for_examples")]
155#[cfg_attr(feature = "docsrs", doc(cfg(feature = "for_examples")))]
156pub mod for_examples;
157
158#[cfg(not(feature = "const_generics"))]
159#[cfg(feature = "cmp_traits")]
160mod for_tupled_reprs;
161
162pub mod asserts;
163
164mod macros;
165mod make_tstr;
166mod to_uint;
167mod tstr_type;
168
169#[cfg(feature = "cmp_traits")]
170mod tstr_cmp;
171
172pub mod utils;
173
174#[doc(hidden)]
175extern crate self as tstr;
176
177#[doc(hidden)]
178pub use tstr_proc_macros::__ts_impl;
179
180pub use crate::{asserts::Assert, make_tstr::MakeTStr, to_uint::ToUint, tstr_type::TStr};
181
182#[cfg(feature = "cmp_traits")]
183pub use tstr_cmp::TStrEq;
184
185#[cfg(all(feature = "cmp_traits", feature = "const_generics"))]
186pub use tstr_cmp::TStrOrd;
187
188#[cfg_attr(feature = "docsrs", doc(cfg(feature = "const_generics")))]
189#[cfg(feature = "const_generics")]
190pub use crate::tstr_type::StrValue;
191
192include! {"./p.rs"}