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}