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}