const_macros/
lib.rs

1//! Various macros for const contexts.
2//!
3//! # Examples
4//!
5//! Below is an example that utilizes most of the macros provided by this crate.
6//!
7//! ```
8//! use const_macros::{const_assert, const_early, const_ok, const_try};
9//!
10//! use thiserror::Error;
11//!
12//! #[derive(Error, Debug)]
13//! #[error("unexpected length: `{value}`")]
14//! pub struct Error {
15//!     pub value: usize,
16//! }
17//!
18//! impl Error {
19//!     pub const fn new(value: usize) -> Self {
20//!         Self { value }
21//!     }
22//! }
23//!
24//! pub const MIN: usize = 32;
25//! pub const MAX: usize = 96;
26//!
27//! const_assert!(MIN <= MAX);
28//!
29//! #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30//! pub struct Length {
31//!     value: usize,
32//! }
33//!
34//! impl Length {
35//!     pub const fn new(value: usize) -> Result<Self, Error> {
36//!         const_try!(Self::check(value));
37//!
38//!         Ok(unsafe { Self::new_unchecked(value) })
39//!     }
40//!
41//!     pub const fn new_ok(value: usize) -> Option<Self> {
42//!         const_ok!(Self::new(value))
43//!     }
44//!
45//!     pub const fn check(value: usize) -> Result<(), Error> {
46//!         const_early!(value < MIN || value > MAX => Error::new(value));
47//!
48//!         Ok(())
49//!     }
50//!
51//!     pub const unsafe fn new_unchecked(value: usize) -> Self {
52//!         Self { value }
53//!     }
54//!
55//!     pub const MIN: Self = Self::new_ok(MIN).unwrap();
56//!     pub const MAX: Self = Self::new_ok(MAX).unwrap();
57//! }
58//! ```
59
60#![no_std]
61#![deny(missing_docs)]
62
63#[allow(unused_imports)]
64#[doc(hidden)]
65pub mod import {
66    pub use core::{option::Option, result::Result};
67}
68
69/// Similar to the `?` operator used on [`Result`] but for `const` contexts.
70///
71/// Note that no conversions are performed, as it is impossible in `const` contexts.
72#[macro_export]
73macro_rules! const_try {
74    ($result: expr) => {
75        match $result {
76            $crate::import::Result::Ok(value) => value,
77            $crate::import::Result::Err(error) => return $crate::import::Result::Err(error),
78        }
79    };
80}
81
82/// Equivalent to the `?` operator used on [`Option`] but for `const` contexts.
83#[macro_export]
84macro_rules! const_none {
85    ($option: expr) => {
86        match $option {
87            $crate::import::Option::Some(value) => value,
88            $crate::import::Option::None => return $crate::import::Option::None,
89        }
90    };
91}
92
93/// Same as [`Result::ok`] but for `const` contexts.
94#[macro_export]
95macro_rules! const_ok {
96    ($result: expr) => {
97        match $result {
98            $crate::import::Result::Ok(value) => $crate::import::Option::Some(value),
99            $crate::import::Result::Err(_) => $crate::import::Option::None,
100        }
101    };
102}
103
104/// Same as [`Result::err`] but for `const` contexts.
105#[macro_export]
106macro_rules! const_err {
107    ($result: expr) => {
108        match $result {
109            $crate::import::Result::Ok(_) => $crate::import::Option::None,
110            $crate::import::Result::Err(error) => $crate::import::Option::Some(error),
111        }
112    };
113}
114
115/// Returns early with the provided error if the condition is true.
116#[macro_export]
117macro_rules! const_early {
118    ($condition: expr => $error: expr) => {
119        if $condition {
120            return $crate::import::Result::Err($error);
121        }
122    };
123}
124
125/// Similar to [`assert!`] but for `const` contexts.
126#[macro_export]
127macro_rules! const_assert {
128    ($condition: expr) => {
129        const _: () = assert!($condition);
130    };
131}
132
133/// Similar to [`assert_eq!`] but for `const` contexts.
134#[macro_export]
135macro_rules! const_assert_eq {
136    ($left: expr, $right: expr, $(,)?) => {
137        $crate::const_assert!($left == $right);
138    };
139}
140
141/// Similar to [`assert_ne!`] but for `const` contexts.
142#[macro_export]
143macro_rules! const_assert_ne {
144    ($left: expr, $right: expr, $(,)?) => {
145        $crate::const_assert!($left != $right);
146    };
147}