tola_caps/trie/
evaluate.rs

1//! Query types and evaluation logic
2//!
3//! Provides Evaluate trait and boolean query types (Has, And, Or, Not).
4
5use core::marker::PhantomData;
6use crate::primitives::Peano;
7use crate::primitives::{Bool, Present, Absent, GetTail, BoolAnd, BoolOr, BoolNot};
8use crate::primitives::stream::{S, D0};
9use super::node::{Empty, Leaf, Node16};
10use super::capability::Capability;
11
12// =============================================================================
13// Query Types
14// =============================================================================
15
16/// Query: Does the set contain capability Cap?
17pub struct Has<Cap>(PhantomData<Cap>);
18
19/// Conjunction: L AND R
20pub struct And<L, R>(PhantomData<(L, R)>);
21
22/// Disjunction: L OR R
23pub struct Or<L, R>(PhantomData<(L, R)>);
24
25/// Negation: NOT Q
26pub struct Not<Q>(PhantomData<Q>);
27
28// =============================================================================
29// HList for All/Any
30// =============================================================================
31
32/// Empty HList
33pub struct HNil;
34
35/// HList cons cell
36pub struct HCons<H, T>(PhantomData<(H, T)>);
37
38/// All queries must be true (conjunction)
39pub struct All<List>(PhantomData<List>);
40
41/// At least one query must be true (disjunction)
42pub struct Any<List>(PhantomData<List>);
43
44// =============================================================================
45// Evaluate (Main Entry Point)
46// =============================================================================
47
48/// Evaluate a boolean query on a capability set.
49///
50/// Returns `Present` (true) or `Absent` (false).
51#[diagnostic::on_unimplemented(
52    message = "Capability logic requirement evaluated to false or is invalid",
53    label = "Logic '{Query}' is NOT satisfied by capability set '{Self}'",
54    note = "Check if you are missing a required capability or possess a conflicting one."
55)]
56pub trait Evaluate<Query> {
57    type Out: Bool;
58    /// The boolean result of the evaluation as a constant.
59    const RESULT: bool = <Self::Out as Bool>::VALUE;
60}
61
62// =============================================================================
63// EvalAt - Internal depth-aware evaluation
64// =============================================================================
65
66/// Internal trait for evaluating queries at a specific depth
67pub trait EvalAt<Query, Depth> {
68    type Out: Bool;
69}
70
71impl<Cap, Depth> EvalAt<Has<Cap>, Depth> for Empty {
72    type Out = Absent;
73}
74
75// Leaf: Two-tier matching (Identity perfect + Stream fallback)
76// - Same Identity64 type → Stream also matches → Present (perfect!)
77// - Different Identity64 → Stream comparison → Present/Absent (~10^-15 collision)
78// Identity64 provides type documentation, Stream provides actual comparison
79use crate::primitives::stream::{StreamEq, DefaultMaxDepth};
80impl<QCap, StoredCap, Depth> EvalAt<Has<QCap>, Depth> for Leaf<StoredCap>
81where
82    QCap: Capability,
83    StoredCap: Capability,
84    QCap::Stream: StreamEq<StoredCap::Stream, DefaultMaxDepth>,
85{
86    type Out = <QCap::Stream as StreamEq<StoredCap::Stream, DefaultMaxDepth>>::Out;
87}
88
89#[macros::node16]
90impl<QCap, Depth, _Slots_> EvalAt<Has<QCap>, Depth> for _Node16_
91where
92    QCap: Capability,
93    Depth: Peano,
94    QCap::Stream: GetTail<Depth>,
95    Self: RouteQuery<QCap, Depth, QCap::At<Depth>>,
96{
97    type Out = <Self as RouteQuery<QCap, Depth, QCap::At<Depth>>>::Out;
98}
99
100// =============================================================================
101// RouteQuery - 16-ary routing
102// =============================================================================
103
104use crate::primitives::nibble::{Nibble, X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, XA, XB, XC, XD, XE, XF};
105
106pub trait RouteQuery<Cap, Depth, Nib: Nibble> {
107    type Out: Bool;
108}
109
110// 16-ary routing: each nibble Xi routes directly to slot Ni
111// Generated 16 impls using #[node16(for_nibble)]
112#[macros::node16(for_nibble)]
113impl<Cap, Depth, _Slots_> RouteQuery<Cap, Depth, _Nibble_> for _Node16_
114where
115    Cap: Capability,
116    Depth: Peano,
117    _SlotN_: EvalAt<Has<Cap>, S<Depth>>,
118{
119    type Out = <_SlotN_ as EvalAt<Has<Cap>, S<Depth>>>::Out;
120}
121
122// =============================================================================
123// Bucket Evaluation - Identity match + Stream fallback
124// =============================================================================
125//
126// Strategy:
127// 1. Check if QCap matches Head via Identity64 (perfect match)
128// 2. If not, continue searching Tail
129// 3. Stream routes, Identity verifies
130
131use super::node::Bucket;
132
133/// Bucket: Linear search with Identity+Stream hybrid matching
134/// Checks head via Stream, returns Present if match OR continues to tail
135impl<QCap, Head, Tail, Depth> EvalAt<Has<QCap>, Depth> for Bucket<Head, Tail>
136where
137    QCap: Capability,
138    Head: Capability,
139    Tail: EvalAt<Has<QCap>, Depth>,
140    QCap::Stream: StreamEq<Head::Stream, DefaultMaxDepth>,
141    <QCap::Stream as StreamEq<Head::Stream, DefaultMaxDepth>>::Out: BoolOr<<Tail as EvalAt<Has<QCap>, Depth>>::Out>,
142{
143    type Out = <<QCap::Stream as StreamEq<Head::Stream, DefaultMaxDepth>>::Out as BoolOr<<Tail as EvalAt<Has<QCap>, Depth>>::Out>>::Out;
144    // Stream matches head OR tail contains QCap
145}
146
147/// Leaf: Exact Identity64 match (higher priority via &)
148/// This impl is chosen when QCap == StoredCap (same Identity64 type).
149impl<Cap, Depth> EvalAt<Has<Cap>, Depth> for &Leaf<Cap>
150where
151    Cap: Capability,
152{
153    type Out = Present;  // Same Identity64 type = exact match
154}
155
156// =============================================================================
157// Evaluate implementations
158// =============================================================================
159
160/// Direct evaluation for any Capability type.
161impl<Ctx, Cap> Evaluate<Cap> for Ctx
162where
163    Cap: Capability,
164    Ctx: EvalAt<Has<Cap>, D0>,
165{
166    type Out = <Ctx as EvalAt<Has<Cap>, D0>>::Out;
167}
168
169// And<L, R>
170impl<Ctx, L, R> Evaluate<And<L, R>> for Ctx
171where
172    Ctx: Evaluate<L> + Evaluate<R>,
173    <Ctx as Evaluate<L>>::Out: BoolAnd<<Ctx as Evaluate<R>>::Out>,
174{
175    type Out = <<Ctx as Evaluate<L>>::Out as BoolAnd<<Ctx as Evaluate<R>>::Out>>::Out;
176}
177
178// Or<L, R>
179impl<Ctx, L, R> Evaluate<Or<L, R>> for Ctx
180where
181    Ctx: Evaluate<L> + Evaluate<R>,
182    <Ctx as Evaluate<L>>::Out: BoolOr<<Ctx as Evaluate<R>>::Out>,
183{
184    type Out = <<Ctx as Evaluate<L>>::Out as BoolOr<<Ctx as Evaluate<R>>::Out>>::Out;
185}
186
187// Not<Q>
188impl<Ctx, Q> Evaluate<Not<Q>> for Ctx
189where
190    Ctx: Evaluate<Q>,
191    <Ctx as Evaluate<Q>>::Out: BoolNot,
192{
193    type Out = <<Ctx as Evaluate<Q>>::Out as BoolNot>::Out;
194}
195
196// All<HNil>
197impl<Ctx> Evaluate<All<HNil>> for Ctx {
198    type Out = Present;
199}
200
201// All<HCons<H, T>>
202impl<Ctx, H, T> Evaluate<All<HCons<H, T>>> for Ctx
203where
204    Ctx: Evaluate<H> + Evaluate<All<T>>,
205    <Ctx as Evaluate<H>>::Out: BoolAnd<<Ctx as Evaluate<All<T>>>::Out>,
206{
207    type Out = <<Ctx as Evaluate<H>>::Out as BoolAnd<<Ctx as Evaluate<All<T>>>::Out>>::Out;
208}
209
210// Any<HNil>
211impl<Ctx> Evaluate<Any<HNil>> for Ctx {
212    type Out = Absent;
213}
214
215// Any<HCons<H, T>>
216impl<Ctx, H, T> Evaluate<Any<HCons<H, T>>> for Ctx
217where
218    Ctx: Evaluate<H> + Evaluate<Any<T>>,
219    <Ctx as Evaluate<H>>::Out: BoolOr<<Ctx as Evaluate<Any<T>>>::Out>,
220{
221    type Out = <<Ctx as Evaluate<H>>::Out as BoolOr<<Ctx as Evaluate<Any<T>>>::Out>>::Out;
222}
223
224// =============================================================================
225// IsTrue / Require helpers
226// =============================================================================
227
228#[diagnostic::on_unimplemented(
229    message = "Capability requirement failed: {Query}",
230    label = "This capability set violates requirement '{Query}'",
231    note = "Set: {Set}\nCheck if you are missing a required capability or possess a conflicting one."
232)]
233pub trait IsTrue<Set, Query: ?Sized> {}
234
235impl<S, Q: ?Sized> IsTrue<S, Q> for Present {}
236
237/// Wrapper trait to enforce a requirement.
238/// Implemented only when `Evaluate<Q>::Out` is `Present`.
239pub trait Require<Q> {}
240
241impl<C, Q> Require<Q> for C
242where
243    C: Evaluate<Q>,
244    <C as Evaluate<Q>>::Out: IsTrue<C, Q>,
245{
246}
247
248// =============================================================================
249// Macros
250// =============================================================================
251
252/// Build HList for All/Any queries
253#[macro_export]
254macro_rules! hlist {
255    () => { $crate::trie::HNil };
256    ($head:ty $(, $tail:ty)*) => {
257        $crate::trie::HCons<$head, hlist![$($tail),*]>
258    };
259}
260
261/// Macro for All query
262#[macro_export]
263macro_rules! all {
264    ($($item:ty),* $(,)?) => {
265        $crate::trie::All<hlist![$($item),*]>
266    };
267}
268
269/// Macro for Any query
270#[macro_export]
271macro_rules! any {
272    ($($item:ty),* $(,)?) => {
273        $crate::trie::Any<hlist![$($item),*]>
274    };
275}