konst/
lib.rs

1//! Const equivalents of std functions, compile-time comparison, and parsing.
2//!
3//! # Features
4//!
5//! This crate provides:
6//!
7//! - Const fn equivalents of standard library functions and methods.
8//!
9//! - Compile-time parsing through the [`Parser`] type, and [`parse_any`] macro.
10//!
11//! - Functions for comparing many standard library types,
12//! with the [`const_eq`]/[`const_eq_for`]/[`const_cmp`]/[`const_cmp_for`] macros
13//! for more conveniently calling them, powered by the [`polymorphism`] module.
14//!
15//!
16//! # Examples
17//!
18//! ### Parsing an enum
19//!
20//! This example demonstrates how you can parse a simple enum from an environment variable,
21//! at compile-time.
22//!
23//! ```rust
24//! use konst::eq_str;
25//! use konst::{unwrap_opt_or, unwrap_ctx};
26//!
27//! #[derive(Debug, PartialEq)]
28//! enum Direction {
29//!     Forward,
30//!     Backward,
31//!     Left,
32//!     Right,
33//! }
34//!
35//! impl Direction {
36//!     const fn try_parse(input: &str) -> Result<Self, ParseDirectionError> {
37//!         // As of Rust 1.51.0, string patterns don't work in const contexts
38//!         match () {
39//!             _ if eq_str(input, "forward") => Ok(Direction::Forward),
40//!             _ if eq_str(input, "backward") => Ok(Direction::Backward),
41//!             _ if eq_str(input, "left") => Ok(Direction::Left),
42//!             _ if eq_str(input, "right") => Ok(Direction::Right),
43//!             _ => Err(ParseDirectionError),
44//!         }
45//!     }
46//! }
47//!
48//! const CHOICE: &str = unwrap_opt_or!(option_env!("chosen-direction"), "forward");
49//!
50//! const DIRECTION: Direction = unwrap_ctx!(Direction::try_parse(CHOICE));
51//!
52//! fn main() {
53//!     match DIRECTION {
54//!         Direction::Forward => assert_eq!(CHOICE, "forward"),
55//!         Direction::Backward => assert_eq!(CHOICE, "backward"),
56//!         Direction::Left => assert_eq!(CHOICE, "left"),
57//!         Direction::Right => assert_eq!(CHOICE, "right"),
58//!     }
59//! }
60//! # #[derive(Debug, PartialEq)]
61//! # pub struct ParseDirectionError;
62//! #
63//! # use std::fmt::{self, Display};
64//! #
65//! # impl Display for ParseDirectionError {
66//! #   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67//! #       f.write_str("Failed to parse a Direction")
68//! #   }
69//! # }
70//! #
71//! # impl ParseDirectionError {
72//! #    #[allow(unconditional_panic)]
73//! #    const fn panic(&self) -> ! {
74//! #        [/*failed to parse a Direction*/][0]
75//! #    }
76//! # }
77//! #
78//! #
79//!
80//! ```
81//!
82//! ### Parsing CSV
83//!
84//! This example demonstrates how an CSV environment variable can be parsed into integers.
85//!
86//! This requires the `"rust_1_64"` and `""parsing_no_proc""` features
87//! (the latter is enabled by default).
88//!
89#![cfg_attr(
90    all(feature = "parsing_no_proc", feature = "rust_1_64"),
91    doc = "```rust"
92)]
93#![cfg_attr(
94    not(all(feature = "parsing_no_proc", feature = "rust_1_64")),
95    doc = "```ignore"
96)]
97//! use konst::{
98//!     primitive::parse_u64,
99//!     result::unwrap_ctx,
100//!     iter, string,
101//! };
102//!
103//! # /*
104//! const CSV: &str = env!("NUMBERS");
105//! # */
106//! # const CSV: &str = "3, 8, 13, 21, 34";
107//!
108//! static PARSED: [u64; 5] = iter::collect_const!(u64 =>
109//!     string::split(CSV, ","),
110//!         map(string::trim),
111//!         map(|s| unwrap_ctx!(parse_u64(s))),
112//! );
113//!
114//! assert_eq!(PARSED, [3, 8, 13, 21, 34]);
115//!
116//! ```
117//!
118//! ### Parsing a struct
119//!
120//! This example demonstrates how you can use [`Parser`] to parse a struct at compile-time.
121//!
122#![cfg_attr(feature = "parsing", doc = "```rust")]
123#![cfg_attr(not(feature = "parsing"), doc = "```ignore")]
124//! use konst::{
125//!     parsing::{Parser, ParseValueResult},
126//!     for_range, parse_any, try_rebind, unwrap_ctx,
127//! };
128//!
129//! const PARSED: Struct = {
130//!     // You can also parse strings from environment variables, or from an `include_str!(....)`
131//!     let input = "\
132//!         1000,
133//!         circle,
134//!         red, blue, green, blue,
135//!     ";
136//!     
137//!     unwrap_ctx!(parse_struct(Parser::from_str(input))).0
138//! };
139//!
140//! fn main(){
141//!     assert_eq!(
142//!         PARSED,
143//!         Struct{
144//!             amount: 1000,
145//!             repeating: Shape::Circle,
146//!             colors: [Color::Red, Color::Blue, Color::Green, Color::Blue],
147//!         }
148//!     );
149//! }
150//!
151//! #[derive(Debug, Clone, PartialEq, Eq)]
152//! pub struct Struct {
153//!     pub amount: usize,
154//!     pub repeating: Shape,
155//!     pub colors: [Color; 4],
156//! }
157//!
158//! #[derive(Debug, Clone, PartialEq, Eq)]
159//! pub enum Shape {
160//!     Circle,
161//!     Square,
162//!     Line,
163//! }
164//!
165//! #[derive(Debug, Copy, Clone, PartialEq, Eq)]
166//! pub enum Color {
167//!     Red,
168//!     Blue,
169//!     Green,
170//! }
171//!
172//! pub const fn parse_struct(mut parser: Parser<'_>) -> ParseValueResult<'_, Struct> {
173//!     try_rebind!{(let amount, parser) = parser.trim_start().parse_usize()}
174//!     try_rebind!{parser = parser.strip_prefix(",")}
175//!
176//!     try_rebind!{(let repeating, parser) = parse_shape(parser.trim_start())}
177//!     try_rebind!{parser = parser.strip_prefix(",")}
178//!
179//!     try_rebind!{(let colors, parser) = parse_colors(parser.trim_start())}
180//!
181//!     Ok((Struct{amount, repeating, colors}, parser))
182//! }
183//!
184//! pub const fn parse_shape(mut parser: Parser<'_>) -> ParseValueResult<'_, Shape> {
185//!     let shape = parse_any!{parser, strip_prefix;
186//!         "circle" => Shape::Circle,
187//!         "square" => Shape::Square,
188//!         "line" => Shape::Line,
189//!         _ => return Err(parser.into_other_error())
190//!     };
191//!     Ok((shape, parser))
192//! }
193//!
194//! pub const fn parse_colors(mut parser: Parser<'_>) -> ParseValueResult<'_, [Color; 4]> {
195//!     let mut colors = [Color::Red; 4];
196//!
197//!     for_range!{i in 0..4 =>
198//!         try_rebind!{(colors[i], parser) = parse_color(parser.trim_start())}
199//!         try_rebind!{parser = parser.strip_prefix(",")}
200//!     }
201//!
202//!     Ok((colors, parser))
203//! }
204//!
205//! pub const fn parse_color(mut parser: Parser<'_>) -> ParseValueResult<'_, Color> {
206//!     let color = parse_any!{parser, strip_prefix;
207//!         "red" => Color::Red,
208//!         "blue" => Color::Blue,
209//!         "green" => Color::Green,
210//!         _ => return Err(parser.into_other_error())
211//!     };
212//!     Ok((color, parser))
213//! }
214//!
215//!
216//!
217//! ```
218//!
219//! # Cargo features
220//!
221//! These are the features of these crates:
222//!
223//! - `"cmp"`(enabled by default):
224//! Enables all comparison functions and macros,
225//! the string equality and ordering comparison functions don't require this feature.
226//!
227//! - `"parsing"`(enabled by default):
228//! Enables the `"parsing_no_proc"` feature, compiles the `konst_proc_macros` dependency,
229//! and enables the [`parse_any`] macro.
230//! You can use this feature instead of `"parsing_no_proc"` if the slightly longer
231//! compile times aren't a problem.
232//!
233//! - `"parsing_no_proc"`(enabled by default):
234//! Enables the [`parsing`] module (for parsing from `&str` and `&[u8]`),
235//! the `primitive::parse_*` functions, `try_rebind`, and `rebind_if_ok` macros.
236//!
237//! - `alloc"`:
238//! Enables items that use types from the [`alloc`] crate, including `Vec` and `String`.
239//!
240//! ### Rust release related
241//!
242//! None of thse features are enabled by default.
243//!
244//! - `"rust_1_51"`:
245//! Enables items that require const generics,
246//! and impls for arrays to use const generics instead of only supporting small arrays.
247//!
248//! - `"rust_1_55"`: Enables the `string::from_utf8` function
249//! (the macro works in all versions),
250//! `str` indexing functions,  and the `"rust_1_51"` feature.
251//!
252//! - `"rust_1_56"`:
253//! Enables items that internally use raw pointer dereferences or transmutes,
254//! and the `"rust_1_55"` feature.
255//!
256//! - `"rust_1_57"`: Allows `konst` to use the `panic` macro,
257//! and enables the `"rust_1_56"` feature.
258//!
259//! - `"rust_1_61"`:
260//! Enables const fns that use trait bounds, and the `"rust_1_57"` feature.
261//!
262//! - `"rust_1_64"`:<br>
263//! Adds slice and string iterators,
264//! string splitting functions(`[r]split_once`),
265//! const equivalents of iterator methods(in `konst::iter`),
266//! and makes slicing functions more efficient.
267//! <br>Note that only functions which mention this feature in their documentation are affected.
268//! <br>Enables the `"rust_1_61"` feature.
269//!
270//! - `"rust_latest_stable"`: enables the latest `"rust_1_*"` feature.
271//! Only recommendable if you can update the Rust compiler every stable release.
272//!
273//! - `"mut_refs"`(disabled by default):
274//! Enables const functions that take mutable references.
275//! Use this whenever mutable references in const contexts are stabilized.
276//! Also enables the `"rust_latest_stable"` feature.
277//!
278//! - `"nightly_mut_refs"`(disabled by default):
279//! Enables the `"mut_refs"` feature. Requires Rust nightly.
280//!
281//! # No-std support
282//!
283//! `konst` is `#![no_std]`, it can be used anywhere Rust can be used.
284//!
285//! # Minimum Supported Rust Version
286//!
287//! `konst` requires Rust 1.46.0, because it uses looping an branching in const contexts.
288//!
289//! Features that require newer versions of Rust, or the nightly compiler,
290//! need to be explicitly enabled with cargo features.
291//!
292//!
293//!
294//! [`alloc`]: https://doc.rust-lang.org/alloc/
295//! [`const_eq`]: ./macro.const_eq.html
296//! [`const_eq_for`]: ./macro.const_eq_for.html
297//! [`const_cmp`]: ./macro.const_cmp.html
298//! [`const_cmp_for`]: ./macro.const_cmp_for.html
299//! [`polymorphism`]: ./polymorphism/index.html
300//! [`parsing`]: ./parsing/index.html
301//! [`primitive`]: ./primitive/index.html
302//! [`parse_any`]: macro.parse_any.html
303//! [`Parser`]: ./parsing/struct.Parser.html
304//! [`Parser::parse_u128`]: ./parsing/struct.Parser.html#method.parse_u128
305//!
306#![deny(missing_docs)]
307#![cfg_attr(
308    feature = "nightly_mut_refs",
309    feature(const_mut_refs, const_slice_from_raw_parts_mut)
310)]
311#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
312#![no_std]
313
314#[cfg(feature = "alloc")]
315extern crate alloc;
316
317#[macro_use]
318mod macros;
319
320///
321#[cfg(feature = "__test")]
322pub mod doctests;
323
324#[doc(hidden)]
325pub mod __for_cmp_impls;
326
327// pub mod other;
328
329#[cfg(feature = "alloc")]
330#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
331pub mod alloc_type;
332
333pub mod array;
334
335pub mod iter;
336
337#[cfg(feature = "cmp")]
338#[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp")))]
339pub mod polymorphism;
340
341pub mod primitive;
342
343pub mod option;
344
345pub mod result;
346
347pub mod range;
348
349pub mod maybe_uninit;
350
351#[cfg(feature = "rust_1_56")]
352#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
353pub mod manually_drop;
354
355pub mod nonzero;
356
357pub mod other;
358
359#[cfg(feature = "parsing_no_proc")]
360#[cfg_attr(feature = "docsrs", doc(cfg(feature = "parsing_no_proc")))]
361pub mod parsing;
362
363pub mod ptr;
364
365mod utils;
366
367#[cfg(feature = "rust_1_56")]
368mod utils_1_56 {
369    pub(crate) use konst_macro_rules::__priv_transmute;
370    pub(crate) use konst_macro_rules::__priv_transmute_ref;
371    pub(crate) use konst_macro_rules::utils_1_56::PtrToRef;
372}
373
374#[cfg(feature = "mut_refs")]
375mod utils_mut;
376
377#[cfg(feature = "parsing_no_proc")]
378#[cfg_attr(feature = "docsrs", doc(cfg(feature = "parsing_no_proc")))]
379pub use crate::parsing::Parser;
380
381#[cfg(feature = "parsing")]
382#[doc(hidden)]
383pub use konst_proc_macros::{__priv_bstr_end, __priv_bstr_start};
384
385pub mod slice;
386
387pub mod string;
388
389pub use crate::string::{cmp_str, eq_str};
390
391#[doc(no_inline)]
392pub use crate::result::unwrap_ctx;
393
394#[cfg(feature = "cmp")]
395#[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp")))]
396pub use crate::string::{cmp_option_str, eq_option_str};
397
398#[doc(hidden)]
399pub mod __ {
400    pub use core::{
401        cmp::Ordering::{self, Equal, Greater, Less},
402        compile_error, matches,
403        ops::Range,
404        option::Option::{self, None, Some},
405        result::Result::{self, Err, Ok},
406    };
407
408    pub mod v {
409        pub use core::{
410            option::Option::Some,
411            result::Result::{Err, Ok},
412        };
413    }
414
415    pub use crate::__for_cmp_impls::U8Ordering;
416
417    #[cfg(feature = "cmp")]
418    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp")))]
419    pub use crate::polymorphism::{
420        CmpWrapper, ConstCmpMarker, IsAConstCmpMarker, IsNotStdKind, IsStdKind,
421    };
422}