tola_caps/spec/dispatch.rs
1//! Type-Level Dispatch System
2//!
3//! Provides zero-overhead method dispatch based on capabilities.
4//! Uses pure type selection instead of `if` branches.
5//!
6//! ## Core Concepts
7//!
8//! 1. `SelectCap<Query, Then, Else>` - Selects `Then` or `Else` based on capability
9//! 2. Uses `Bool::If<Then, Else>` for type-level selection
10//! 3. Works with existing `Evaluate` trait
11//!
12//! ## Example
13//!
14//! ```ignore
15//! // Define implementations as types
16//! struct CloneImpl;
17//! struct DefaultImpl;
18//!
19//! impl<T> MethodImpl<T> for CloneImpl { ... }
20//! impl<T> MethodImpl<T> for DefaultImpl { ... }
21//!
22//! // Select at type level
23//! type Selected = <Cap<MyType> as SelectCap<IsClone, CloneImpl, DefaultImpl>>::Out;
24//! Selected::method(&value) // No if branch!
25//! ```
26
27use crate::primitives::{Bool, Present, Absent};
28use crate::trie::{Evaluate, And, Or, Not};
29
30// Re-export select traits from detect module (only when detect feature is enabled)
31#[cfg(feature = "detect")]
32pub use crate::detect::{
33 SelectClone, SelectCopy, SelectDebug, SelectDefault,
34 SelectSend, SelectSync, SelectEq, SelectPartialEq,
35 SelectOrd, SelectPartialOrd, SelectHash,
36 SelectDisplay, SelectSized, SelectUnpin,
37};
38
39// =============================================================================
40// SelectCap Trait - Core Type-Level Selector
41// =============================================================================
42
43/// Selects between two types based on a capability query.
44///
45/// Given a capability set `S`, a query `Q`, and two candidate types `Then`/`Else`:
46/// - If `S: Evaluate<Q, Out = Present>`, returns `Then`
47/// - If `S: Evaluate<Q, Out = Absent>`, returns `Else`
48pub trait SelectCap<Q, Then, Else> {
49 type Out;
50}
51
52impl<S, Q, Then, Else> SelectCap<Q, Then, Else> for S
53where
54 S: Evaluate<Q>,
55 <S as Evaluate<Q>>::Out: Bool,
56{
57 type Out = <<S as Evaluate<Q>>::Out as Bool>::If<Then, Else>;
58}
59
60/// Call a static method based on capability selection.
61///
62/// This trait enables calling `StaticMethodImpl::call()` through type-level selection
63/// without requiring the caller to prove that `SelectCap::Out` implements `StaticMethodImpl`.
64///
65/// `Then` and `Else` must implement `StaticMethodImpl<Output>`.
66pub trait SelectStaticCall<Q, Then, Else, Output> {
67 fn call() -> Output;
68}
69
70impl<S, Q, Then, Else, Output> SelectStaticCall<Q, Then, Else, Output> for S
71where
72 S: Evaluate<Q>,
73 <S as Evaluate<Q>>::Out: Bool,
74 Then: StaticMethodImpl<Output>,
75 Else: StaticMethodImpl<Output>,
76{
77 #[inline(always)]
78 fn call() -> Output {
79 <S as Evaluate<Q>>::Out::static_dispatch::<Then, Else, Output>()
80 }
81}
82
83/// Helper trait for calling static methods through Bool selection.
84///
85/// This trait is implemented for `Present` and `Absent` to enable
86/// type-level branching for static method calls.
87pub trait BoolStaticCall<Then, Else, Output> {
88 fn call() -> Output;
89}
90
91impl<Then, Else, Output> BoolStaticCall<Then, Else, Output> for Present
92where
93 Then: StaticMethodImpl<Output>,
94{
95 #[inline(always)]
96 fn call() -> Output {
97 Then::call()
98 }
99}
100
101impl<Then, Else, Output> BoolStaticCall<Then, Else, Output> for Absent
102where
103 Else: StaticMethodImpl<Output>,
104{
105 #[inline(always)]
106 fn call() -> Output {
107 Else::call()
108 }
109}
110
111/// Wrapper type for chaining static method selections.
112///
113/// This type wraps a `SelectStaticCall` to itself implement `StaticMethodImpl`,
114/// enabling nested selections.
115pub struct StaticSelect<Cap, Q, Then, Else>(
116 core::marker::PhantomData<(Cap, Q, Then, Else)>
117);
118
119impl<Cap, Q, Then, Else, Output> StaticMethodImpl<Output> for StaticSelect<Cap, Q, Then, Else>
120where
121 Cap: SelectStaticCall<Q, Then, Else, Output>,
122{
123 #[inline(always)]
124 fn call() -> Output {
125 <Cap as SelectStaticCall<Q, Then, Else, Output>>::call()
126 }
127}
128
129// =============================================================================
130// Compound Selectors (And, Or, Not)
131// =============================================================================
132
133/// Select based on multiple capabilities (AND)
134pub trait SelectAnd<Q1, Q2, Then, Else> {
135 type Out;
136}
137
138impl<S, Q1, Q2, Then, Else> SelectAnd<Q1, Q2, Then, Else> for S
139where
140 S: SelectCap<And<Q1, Q2>, Then, Else>,
141{
142 type Out = <S as SelectCap<And<Q1, Q2>, Then, Else>>::Out;
143}
144
145/// Select based on either capability (OR)
146pub trait SelectOr<Q1, Q2, Then, Else> {
147 type Out;
148}
149
150impl<S, Q1, Q2, Then, Else> SelectOr<Q1, Q2, Then, Else> for S
151where
152 S: SelectCap<Or<Q1, Q2>, Then, Else>,
153{
154 type Out = <S as SelectCap<Or<Q1, Q2>, Then, Else>>::Out;
155}
156
157/// Select based on absence of capability (NOT)
158pub trait SelectNot<Q, Then, Else> {
159 type Out;
160}
161
162impl<S, Q, Then, Else> SelectNot<Q, Then, Else> for S
163where
164 S: SelectCap<Not<Q>, Then, Else>,
165{
166 type Out = <S as SelectCap<Not<Q>, Then, Else>>::Out;
167}
168
169// =============================================================================
170// Method Implementation Trait
171// =============================================================================
172
173/// Trait for method implementations that can be type-selected.
174pub trait MethodImpl<T: ?Sized, Output = ()> {
175 fn call(value: &T) -> Output;
176}
177
178/// Trait for static/associated function implementations (no self parameter).
179pub trait StaticMethodImpl<Output = ()> {
180 fn call() -> Output;
181}
182
183// =============================================================================
184// Type Selection Trait (for associated types)
185// =============================================================================
186
187/// Selects between two types based on a capability query (for associated types).
188pub trait SelectType<Q, Then, Else> {
189 type Out;
190}
191
192impl<S, Q, Then, Else> SelectType<Q, Then, Else> for S
193where
194 S: Evaluate<Q>,
195 <S as Evaluate<Q>>::Out: Bool,
196{
197 type Out = <<S as Evaluate<Q>>::Out as Bool>::If<Then, Else>;
198}
199
200/// Trait for type selectors - used by specialize! for associated types.
201pub trait TypeSelector {
202 type Out;
203}
204
205// =============================================================================
206// NoImpl - Fallback for when no implementation matches
207// =============================================================================
208
209/// Marker type for when no specialized implementation is available.
210pub struct NoImpl;
211
212impl<T: ?Sized, Output: Default> MethodImpl<T, Output> for NoImpl {
213 #[inline(always)]
214 fn call(_value: &T) -> Output {
215 Output::default()
216 }
217}
218
219impl<Output: Default> StaticMethodImpl<Output> for NoImpl {
220 #[inline(always)]
221 fn call() -> Output {
222 Output::default()
223 }
224}
225
226impl TypeSelector for NoImpl {
227 type Out = ();
228}