1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! Use a runtime `u64` as a `const N: u64`, safely.
//!
//! Const generics in Rust have to be known at compile time. That's
//! frustrating when the value you actually want to parameterize on
//! (a modulus, a buffer size, a feature flag) only becomes known at
//! runtime. The orthodox workarounds are to drop the const generic
//! (and lose the type safety), or to write a giant `match` by hand.
//!
//! This crate is the giant `match`, generated for you, with three
//! progressively more powerful APIs on top.
//!
//! Everything is `#![deny(unsafe_code)]`. There is no vtable
//! fabrication, no `transmute`, no UB. The dispatch is a flat 256-arm
//! `match` that the compiler optimizes well. The tradeoff: the runtime
//! value must lie in `0..=255` per dispatch (and the trait this crate
//! ships with is just one example; you can build your own with a wider
//! range). For the full safety analysis and why we chose this over the
//! original "fabricate a vtable" approach, see [`DESIGN.md`][design].
//!
//! [design]: https://github.com/joshburgess/reify-reflect/blob/main/const-reify/DESIGN.md
//!
//! # Three APIs, in order of power
//!
//! ## 1. [`reify_const`] / [`reify!`]
//!
//! Smallest surface area. You get a `&dyn HasModulus` whose
//! [`modulus()`](HasModulus::modulus) returns your runtime value. The
//! const generic is "real" inside the dispatch (each arm calls
//! `Modular::<N>::new()`), but you can only see it through the
//! [`HasModulus`] trait. Useful for testing the wiring.
//!
//! ```
//! use const_reify::{reify_const, HasModulus};
//!
//! let result = reify_const(17, |m| m.modulus());
//! assert_eq!(result, 17);
//! ```
//!
//! ## 2. [`reify_nat_fn`] / [`reify_nat2_fn`]
//!
//! When you only need the runtime value as a plain `u64` inside the
//! callback (no const generic gymnastics needed). The closure form is
//! the easiest entry point and is enough for most ad-hoc uses.
//!
//! ```
//! use const_reify::reify_nat_fn;
//!
//! let squared = reify_nat_fn(12, |n| n * n);
//! assert_eq!(squared, 144);
//! ```
//!
//! ## 3. [`NatCallback`] / [`reify_nat`]
//!
//! The full power form. Implement [`NatCallback`] on a type, and inside
//! [`call::<const N: u64>()`](NatCallback::call) the value `N` is a
//! genuine const generic that you can use in `const N: u64` positions.
//!
//! ```
//! use const_reify::nat_reify::{NatCallback, reify_nat};
//!
//! struct Square;
//! impl NatCallback<u64> for Square {
//! fn call<const N: u64>(&self) -> u64 { N * N }
//! }
//!
//! assert_eq!(reify_nat(7, &Square), 49);
//! ```
//!
//! For traits with multiple const-generic methods, the
//! [`#[reifiable]`](https://docs.rs/const-reify-derive) proc macro
//! generates the `NatCallback` plumbing automatically. See
//! [Guide 4][guide4].
//!
//! [guide4]: https://github.com/joshburgess/reify-reflect/blob/main/docs/guides/04-reifiable-macro.md
//!
//! # See also
//!
//! - [`docs/phase5-const-reify.md`][phase5] for the design rationale,
//! including why the range is 256 and why this is fully safe despite
//! the "vtable fabrication" reputation of the underlying technique.
//! - The [narrative blog post][blog] for a worked example using modular
//! arithmetic.
//!
//! [phase5]: https://github.com/joshburgess/reify-reflect/blob/main/docs/phase5-const-reify.md
//! [blog]: https://github.com/joshburgess/reify-reflect/blob/main/docs/blog-post.md
pub use ;
pub use ;
/// Maximum supported value for [`reify_const`] dispatch.
pub const MAX_REIFY_VALUE: u64 = 255;
/// Convenience macro for runtime-to-const-generic dispatch.
///
/// # Examples
///
/// ```
/// use const_reify::{reify, HasModulus};
///
/// reify!(10u64, |m: &dyn HasModulus| {
/// assert_eq!(m.modulus(), 10);
/// });
/// ```
///
/// # Panics
///
/// Panics if the value exceeds [`MAX_REIFY_VALUE`] (255).