tola_caps/trie/
ops.rs

1//! Set operations on capability tries: Union, Intersect, SupersetOf, SetAnd
2//!
3//! These traits enable combining and comparing capability sets at the type level.
4
5use crate::primitives::{Present, Absent, Bool};
6use crate::primitives::stream::{StreamEq, DefaultMaxDepth};
7use super::node::{Empty, Leaf, Node16};
8use super::capability::Capability;
9use super::insert::With;
10
11// =============================================================================
12// Set Operations Traits
13// =============================================================================
14
15/// Set Union: Merge two capability sets.
16/// Returns a set containing all capabilities from both A and B.
17pub trait SetUnion<Other> {
18    type Out;
19}
20
21/// Set Intersection: Common capabilities between two sets.
22/// Returns a set containing only capabilities present in both A and B.
23pub trait SetIntersect<Other> {
24    type Out;
25}
26
27/// SupersetOf: Check if Self contains all capabilities in Other.
28/// Used for downcasting / forgetting extra capabilities.
29pub trait SupersetOf<Other>: Sized {}
30
31/// Structural set intersection (Cap1 & Cap2).
32pub trait SetAnd<Other> {
33    type Out;
34}
35
36// =============================================================================
37// SetUnion Implementations
38// =============================================================================
39
40// Empty ∪ X = X
41impl<T> SetUnion<T> for Empty {
42    type Out = T;
43}
44
45// Leaf<A> ∪ Empty = Leaf<A>
46impl<A> SetUnion<Empty> for Leaf<A> {
47    type Out = Leaf<A>;
48}
49
50// Node16 ∪ Empty = Node16
51#[macros::node16]
52impl<_Slots_> SetUnion<Empty> for _Node16_ {
53    type Out = Self;
54}
55
56// Leaf<A> ∪ Leaf<B> = Insert B into Leaf<A>
57impl<A, B> SetUnion<Leaf<B>> for Leaf<A>
58where
59    B: Capability,
60    Leaf<A>: With<B>,
61{
62    type Out = <Leaf<A> as With<B>>::Out;
63}
64
65// Leaf<A> ∪ Node16<...> = Insert A into Node16
66#[macros::node16]
67impl<A, _Slots_> SetUnion<_Node16_> for Leaf<A>
68where
69    A: Capability,
70    _Node16_: With<A>,
71{
72    type Out = <_Node16_ as With<A>>::Out;
73}
74
75// Node16 ∪ Leaf<A> = Insert A into Node16
76#[macros::node16]
77impl<A, _Slots_> SetUnion<Leaf<A>> for _Node16_
78where
79    A: Capability,
80    Self: With<A>,
81{
82    type Out = <Self as With<A>>::Out;
83}
84
85// =============================================================================
86// SetIntersect Implementations
87// =============================================================================
88
89// Empty ∩ X = Empty
90impl<T> SetIntersect<T> for Empty {
91    type Out = Empty;
92}
93
94// X ∩ Empty = Empty
95impl<A> SetIntersect<Empty> for Leaf<A> {
96    type Out = Empty;
97}
98
99#[macros::node16]
100impl<_Slots_> SetIntersect<Empty> for _Node16_ {
101    type Out = Empty;
102}
103
104// Leaf<A> ∩ Leaf<B> = Leaf<A> if A == B, else Empty
105impl<A, B> SetIntersect<Leaf<B>> for Leaf<A>
106where
107    A: Capability,
108    B: Capability,
109    A::Stream: StreamEq<B::Stream, DefaultMaxDepth>,
110    <A::Stream as StreamEq<B::Stream, DefaultMaxDepth>>::Out: IntersectLeafHelper<A>,
111{
112    type Out = <<A::Stream as StreamEq<B::Stream, DefaultMaxDepth>>::Out as IntersectLeafHelper<A>>::Out;
113}
114
115/// Helper for conditional Leaf intersection result
116pub trait IntersectLeafHelper<A> {
117    type Out;
118}
119
120impl<A> IntersectLeafHelper<A> for Present {
121    type Out = Leaf<A>;  // Same capability
122}
123
124impl<A> IntersectLeafHelper<A> for Absent {
125    type Out = Empty;  // Different capabilities
126}
127
128// =============================================================================
129// SupersetOf Implementations
130// =============================================================================
131
132// Everything is a superset of Empty
133impl<T> SupersetOf<Empty> for T {}
134
135// Leaf<A> is superset of Leaf<A> (identity)
136impl<A> SupersetOf<Leaf<A>> for Leaf<A> {}
137
138// Node16 is superset of Leaf<A> if it contains A
139use super::evaluate::{Evaluate, Has};
140
141#[macros::node16]
142impl<A, _Slots_> SupersetOf<Leaf<A>> for _Node16_
143where
144    A: Capability,
145    Self: Evaluate<Has<A>, Out = Present>,
146{}
147
148// =============================================================================
149// SetAnd Implementations (Structural Intersection)
150// =============================================================================
151
152// Empty & Anything = Empty
153impl<T> SetAnd<T> for Empty {
154    type Out = Empty;
155}
156
157// Leaf & ... (dispatch based on RHS)
158impl<C, Other> SetAnd<Other> for Leaf<C>
159where
160    Other: LeafAndDispatch<C>,
161{
162    type Out = <Other as LeafAndDispatch<C>>::Out;
163}
164
165pub trait LeafAndDispatch<LLeafCap> {
166    type Out;
167}
168
169// Leaf & Empty = Empty
170impl<C> LeafAndDispatch<C> for Empty {
171    type Out = Empty;
172}
173
174// Leaf & Leaf = Leaf IF same cap, else Empty
175impl<C1, C2> LeafAndDispatch<C1> for Leaf<C2>
176where
177    C1: Capability,
178    C2: Capability,
179    C1::Stream: StreamEq<C2::Stream, DefaultMaxDepth>,
180{
181    type Out = <<C1::Stream as StreamEq<C2::Stream, DefaultMaxDepth>>::Out as Bool>::If<Leaf<C1>, Empty>;
182}
183
184// Leaf & Node = Empty
185#[macros::node16]
186impl<C, _Slots_> LeafAndDispatch<C> for _Node16_ {
187    type Out = Empty;
188}
189
190// Node & ... (dispatch based on RHS)
191#[macros::node16]
192impl<R, _Slots_> SetAnd<R> for _Node16_
193where
194    R: NodeAndDispatch<_Slots_>,
195{
196    type Out = <R as NodeAndDispatch<_Slots_>>::Out;
197}
198
199pub trait NodeAndDispatch<L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF> {
200    type Out;
201}
202
203// Node & Empty = Empty
204impl<L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF>
205    NodeAndDispatch<L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF>
206    for Empty
207{
208    type Out = Empty;
209}
210
211// Node & Leaf = Empty
212impl<C, L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF>
213    NodeAndDispatch<L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF>
214    for Leaf<C>
215{
216    type Out = Empty;
217}
218
219// Node & Node = Node (Slot-by-slot structural intersection)
220#[allow(clippy::type_complexity)]
221impl<
222    R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, RA, RB, RC, RD, RE, RF,
223    L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF,
224>
225    NodeAndDispatch<L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, LA, LB, LC, LD, LE, LF>
226    for Node16<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, RA, RB, RC, RD, RE, RF>
227where
228    L0: SetAnd<R0>, L1: SetAnd<R1>, L2: SetAnd<R2>, L3: SetAnd<R3>,
229    L4: SetAnd<R4>, L5: SetAnd<R5>, L6: SetAnd<R6>, L7: SetAnd<R7>,
230    L8: SetAnd<R8>, L9: SetAnd<R9>, LA: SetAnd<RA>, LB: SetAnd<RB>,
231    LC: SetAnd<RC>, LD: SetAnd<RD>, LE: SetAnd<RE>, LF: SetAnd<RF>,
232{
233    type Out = Node16<
234        <L0 as SetAnd<R0>>::Out, <L1 as SetAnd<R1>>::Out,
235        <L2 as SetAnd<R2>>::Out, <L3 as SetAnd<R3>>::Out,
236        <L4 as SetAnd<R4>>::Out, <L5 as SetAnd<R5>>::Out,
237        <L6 as SetAnd<R6>>::Out, <L7 as SetAnd<R7>>::Out,
238        <L8 as SetAnd<R8>>::Out, <L9 as SetAnd<R9>>::Out,
239        <LA as SetAnd<RA>>::Out, <LB as SetAnd<RB>>::Out,
240        <LC as SetAnd<RC>>::Out, <LD as SetAnd<RD>>::Out,
241        <LE as SetAnd<RE>>::Out, <LF as SetAnd<RF>>::Out,
242    >;
243}