Skip to main content

const_reify/
lib.rs

1#![deny(unsafe_code)]
2
3//! # const-reify
4//!
5//! Runtime-to-const-generic bridge via match-table dispatch.
6//!
7//! Given a runtime `u64` value in `0..=255`, dispatches to the corresponding
8//! monomorphization of a const-generic type, enabling type-level programming
9//! with runtime-determined values.
10//!
11//! See [`DESIGN.md`](https://github.com/joshburgess/reify-reflect/blob/main/const-reify/DESIGN.md)
12//! for the design rationale and safety analysis.
13//!
14//! # Examples
15//!
16//! ```
17//! use const_reify::{reify_const, HasModulus};
18//!
19//! let result = reify_const(17, |m| m.modulus());
20//! assert_eq!(result, 17);
21//! ```
22//!
23//! Using the [`reify!`] macro:
24//!
25//! ```
26//! use const_reify::{reify, HasModulus};
27//!
28//! reify!(42u64, |m: &dyn HasModulus| {
29//!     assert_eq!(m.modulus(), 42);
30//! });
31//! ```
32
33mod dispatch;
34pub mod nat_reify;
35
36pub use dispatch::{reify_const, HasModulus, Modular};
37pub use nat_reify::{
38    reify_nat, reify_nat2, reify_nat2_fn, reify_nat_fn, FnNat, FnNat2, Nat2Callback, NatCallback,
39};
40
41/// Maximum supported value for [`reify_const`] dispatch.
42pub const MAX_REIFY_VALUE: u64 = 255;
43
44/// Convenience macro for runtime-to-const-generic dispatch.
45///
46/// # Examples
47///
48/// ```
49/// use const_reify::{reify, HasModulus};
50///
51/// reify!(10u64, |m: &dyn HasModulus| {
52///     assert_eq!(m.modulus(), 10);
53/// });
54/// ```
55///
56/// # Panics
57///
58/// Panics if the value exceeds [`MAX_REIFY_VALUE`] (255).
59#[macro_export]
60macro_rules! reify {
61    ($val:expr, $f:expr) => {{
62        $crate::reify_const($val, $f)
63    }};
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn reify_zero() {
72        let result = reify_const(0, |m| m.modulus());
73        assert_eq!(result, 0);
74    }
75
76    #[test]
77    fn reify_max() {
78        let result = reify_const(255, |m| m.modulus());
79        assert_eq!(result, 255);
80    }
81
82    #[test]
83    fn reify_arbitrary() {
84        for v in [1, 17, 42, 100, 200, 255] {
85            let result = reify_const(v, |m| m.modulus());
86            assert_eq!(result, v);
87        }
88    }
89
90    #[test]
91    #[should_panic(expected = "out of supported range")]
92    fn reify_out_of_range() {
93        reify_const(256, |m| m.modulus());
94    }
95
96    #[test]
97    fn reify_macro() {
98        reify!(42u64, |m: &dyn HasModulus| { assert_eq!(m.modulus(), 42) });
99    }
100
101    #[test]
102    fn reify_returns_value() {
103        let doubled = reify_const(21, |m| m.modulus() * 2);
104        assert_eq!(doubled, 42);
105    }
106
107    #[test]
108    fn reify_all_values() {
109        for v in 0..=255u64 {
110            assert_eq!(reify_const(v, |m| m.modulus()), v);
111        }
112    }
113}