tola_caps/trie/
insert.rs

1//! Insert and Remove operations for the 16-ary trie
2//!
3//! Provides traits for inserting capabilities into and removing them from the trie.
4
5use crate::primitives::Peano;
6use crate::primitives::{GetTail, Nibble, Present, Absent};
7use crate::primitives::stream::{S, D0, StreamEq, DefaultMaxDepth};
8use crate::primitives::nibble::{NibbleEq, *};
9
10
11use super::node::{Empty, Leaf, Node16, EmptyNode16, Bucket};
12use super::capability::Capability;
13use super::evaluate::{EvalAt, Has};
14
15// =============================================================================
16// InsertAt - Main insertion trait
17// =============================================================================
18
19/// Insert a capability into a trie node at a given depth
20pub trait InsertAt<Cap, Depth> {
21    type Out;
22}
23
24impl<Cap, Depth> InsertAt<Cap, Depth> for Empty {
25    type Out = Leaf<Cap>;
26}
27
28#[macros::node16]
29impl<Cap, Depth, _Slots_> InsertAt<Cap, Depth> for _Node16_
30where
31    Cap: Capability,
32    Depth: Peano,
33    Cap::Stream: GetTail<Depth>,
34    Self: NodeInsert<Cap, Depth, Cap::At<Depth>>,
35{
36    type Out = <Self as NodeInsert<Cap, Depth, Cap::At<Depth>>>::Out;
37}
38
39// =============================================================================
40// NodeInsert - 16-ary node insertion
41// =============================================================================
42
43/// Insert capability into Node16 at specific nibble position
44pub trait NodeInsert<Cap, Depth, Nib: Nibble> {
45    type Out;
46}
47
48
49#[macros::node16(for_nibble_split)]
50impl<Cap, Depth, _Slots_> NodeInsert<Cap, Depth, _Nibble_> for _Node16_
51where
52    Cap: Capability,
53    Depth: Peano,
54    _SlotN_: InsertAt<Cap, S<Depth>>,
55{
56    type Out = Node16<_Before_, <_SlotN_ as InsertAt<Cap, S<Depth>>>::Out, _After_>;
57}
58
59// =============================================================================
60// LeafInsert - Insertion into Leaf nodes
61// =============================================================================
62
63impl<NewCap, StoredCap, Depth> InsertAt<NewCap, Depth> for Leaf<StoredCap>
64where
65    NewCap: Capability,
66    StoredCap: Capability,
67    Depth: Peano,
68    NewCap::Stream: GetTail<Depth>,
69    StoredCap::Stream: GetTail<Depth>,
70    Self: LeafInsert<NewCap, StoredCap, Depth, NewCap::At<Depth>, StoredCap::At<Depth>>,
71{
72    type Out = <Self as LeafInsert<NewCap, StoredCap, Depth, NewCap::At<Depth>, StoredCap::At<Depth>>>::Out;
73}
74
75/// Insert into a Leaf node - handles collision vs diverge cases
76pub trait LeafInsert<NewCap, StoredCap, Depth, NewNib: Nibble, StoredNib: Nibble> {
77    type Out;
78}
79
80// =============================================================================
81// MakeNode16WithLeaf - Helper traits
82// =============================================================================
83
84/// Helper trait to create a Node16 with a single leaf at position Xi
85pub trait MakeNode16WithLeaf<Cap, Nib: Nibble> {
86    type Out;
87}
88
89/// Helper trait to create a Node16 with two leaves at positions
90pub trait MakeNode16WithTwoLeaves<NewCap, StoredCap, NewNib: Nibble, StoredNib: Nibble> {
91    type Out;
92}
93
94
95#[macros::node16(for_nibble_split)]
96impl<Cap> MakeNode16WithLeaf<Cap, _Nibble_> for () {
97    type Out = Node16<_EmptyBefore_, Leaf<Cap>, _EmptyAfter_>;
98}
99
100// =============================================================================
101// LeafInsert - Same nibble collision (16 impls)
102// =============================================================================
103
104// Same nibble collision: both caps go into same slot at NEXT depth
105// Helper trait to dispatch based on Hash Stream Equality (Collision vs Diverge)
106// We include Nibble to ensure uniqueness of impls generated by #[node16(for_nibble_split)]
107pub trait LeafCollisionBranch<NewCap, StoredCap, IsCollision, Depth, Nib: Nibble> {
108    type Out;
109}
110
111// Case 1a: Stream collision AND same type (NewCap == StoredCap) - Deduplicate
112impl<Cap, Depth, Nib> LeafCollisionBranch<Cap, Cap, Present, Depth, Nib> for Leaf<Cap>
113where
114    Cap: Capability,
115    Nib: Nibble,
116{
117    type Out = Leaf<Cap>; // Already present, deduplicate
118}
119
120// Note: Case 1b (Stream collision but different types) would create a Bucket.
121// However, in our current design, we rely on the hash being unique enough
122// that true collisions (different types with same hash) are effectively impossible
123// with 64-bit FNV-1a hash + full module path.
124// If a collision does occur, compilation will fail with "conflicting implementations"
125// which is SAFE (fail-closed) rather than silently wrong behavior.
126
127// Case 2: Diverge -> Deepen
128#[macros::node16(for_nibble_split)]
129impl<NewCap, StoredCap, Depth> LeafCollisionBranch<NewCap, StoredCap, Absent, Depth, _Nibble_> for Leaf<StoredCap>
130where
131    StoredCap: Capability,
132    NewCap: Capability,
133    Empty: InsertAt<StoredCap, S<Depth>>,
134    <Empty as InsertAt<StoredCap, S<Depth>>>::Out: InsertAt<NewCap, S<Depth>>,
135{
136    type Out = Node16<
137        _EmptyBefore_,
138        <<Empty as InsertAt<StoredCap, S<Depth>>>::Out as InsertAt<NewCap, S<Depth>>>::Out,
139        _EmptyAfter_
140    >;
141}
142
143// Same nibble collision: Check for Full Stream Collision first
144#[macros::node16(for_nibble_split)]
145impl<NewCap, StoredCap, Depth> LeafInsert<NewCap, StoredCap, Depth, _Nibble_, _Nibble_> for Leaf<StoredCap>
146where
147    NewCap: Capability,
148    StoredCap: Capability,
149    NewCap::Stream: StreamEq<StoredCap::Stream, DefaultMaxDepth>, // Check for collision
150    Self: LeafCollisionBranch<
151        NewCap,
152        StoredCap,
153        <NewCap::Stream as StreamEq<StoredCap::Stream, DefaultMaxDepth>>::Out,
154        Depth,
155        _Nibble_
156    >,
157{
158    type Out = <Self as LeafCollisionBranch<
159        NewCap,
160        StoredCap,
161        <NewCap::Stream as StreamEq<StoredCap::Stream, DefaultMaxDepth>>::Out,
162        Depth,
163        _Nibble_
164    >>::Out;
165}
166
167// =============================================================================
168// LeafInsert - Different nibbles (single generic impl via NibbleEq)
169// =============================================================================
170
171/// Different nibbles: insert both leaves into EmptyNode16 at current depth.
172/// Uses NibbleEq<Out = Absent> constraint to ensure NewNib != StoredNib.
173impl<NewCap, StoredCap, Depth, NewNib, StoredNib>
174    LeafInsert<NewCap, StoredCap, Depth, NewNib, StoredNib> for Leaf<StoredCap>
175where
176    NewCap: Capability,
177    StoredCap: Capability,
178    NewNib: Nibble + NibbleEq<StoredNib, Out = Absent>,
179    StoredNib: Nibble,
180    EmptyNode16: NodeInsert<StoredCap, Depth, StoredNib>,
181    <EmptyNode16 as NodeInsert<StoredCap, Depth, StoredNib>>::Out:
182        NodeInsert<NewCap, Depth, NewNib>,
183{
184    type Out = <<EmptyNode16 as NodeInsert<StoredCap, Depth, StoredNib>>::Out
185        as NodeInsert<NewCap, Depth, NewNib>>::Out;
186}
187
188// =============================================================================
189// RemoveAt - Main removal trait
190// =============================================================================
191
192/// Remove a capability from a trie node at a given depth
193pub trait RemoveAt<Cap, Depth> {
194    type Out;
195}
196
197impl<Cap, Depth> RemoveAt<Cap, Depth> for Empty {
198    type Out = Empty;
199}
200
201// =============================================================================
202// LeafRemove - Removal from Leaf nodes
203// =============================================================================
204
205/// Remove from a Leaf node based on match result
206pub trait LeafRemove<IsMatch> {
207    type Out;
208}
209
210impl<S> LeafRemove<Present> for Leaf<S> {
211    type Out = Empty;
212}
213
214impl<S> LeafRemove<Absent> for Leaf<S> {
215    type Out = Leaf<S>;
216}
217
218impl<StoredCap, QCap, Depth> RemoveAt<QCap, Depth> for Leaf<StoredCap>
219where
220    QCap: Capability,
221    StoredCap: Capability,
222    Leaf<StoredCap>: EvalAt<Has<QCap>, Depth>,
223    Leaf<StoredCap>: LeafRemove<<Leaf<StoredCap> as EvalAt<Has<QCap>, Depth>>::Out>,
224{
225    type Out = <Leaf<StoredCap> as LeafRemove<<Leaf<StoredCap> as EvalAt<Has<QCap>, Depth>>::Out>>::Out;
226}
227
228// =============================================================================
229// NodeRemove - 16-ary node removal
230// =============================================================================
231
232/// Remove capability from Node16 at specific nibble position
233pub trait NodeRemove<Cap, Depth, Nib: Nibble> {
234    type Out;
235}
236
237
238#[macros::node16(for_nibble_split)]
239impl<Cap, Depth, _Slots_> NodeRemove<Cap, Depth, _Nibble_> for _Node16_
240where
241    Cap: Capability,
242    _SlotN_: RemoveAt<Cap, S<Depth>>,
243{
244    type Out = Node16<_Before_, <_SlotN_ as RemoveAt<Cap, S<Depth>>>::Out, _After_>;
245}
246
247#[macros::node16]
248impl<Cap, Depth, _Slots_> RemoveAt<Cap, Depth> for _Node16_
249where
250    Cap: Capability,
251    Depth: Peano,
252    Cap::Stream: GetTail<Depth>,
253    Self: NodeRemove<Cap, Depth, Cap::At<Depth>>,
254{
255    type Out = <Self as NodeRemove<Cap, Depth, Cap::At<Depth>>>::Out;
256}
257
258// =============================================================================
259// Bucket Operations (Linear Scan)
260// =============================================================================
261
262// InsertAt for Bucket - same type at head means already present
263impl<Cap, Tail, Depth> InsertAt<Cap, Depth> for Bucket<Cap, Tail>
264where
265    Cap: Capability,
266{
267    type Out = Self; // Already present
268}
269
270// RemoveAt for Bucket - same type at head means remove head
271impl<Cap, Tail, Depth> RemoveAt<Cap, Depth> for Bucket<Cap, Tail>
272where
273    Cap: Capability,
274{
275    type Out = Tail; // Remove head
276}
277
278// =============================================================================
279// With / Without - User-facing API for adding/removing capabilities
280// =============================================================================
281
282/// Add a capability to a set (user-facing API)
283///
284/// This trait wraps `InsertAt` with depth=D0 for a cleaner API.
285/// ```ignore
286/// type MySet = <Empty as With<CloneCap>>::Out;
287/// ```
288#[diagnostic::on_unimplemented(
289    message = "Cannot add capability {Cap} to set {Self}",
290    label = "Failed to add {Cap} to {Self}",
291    note = "Ensure {Self} is a valid capability set (Empty/Leaf/Node) and {Cap} is a Capability."
292)]
293pub trait With<Cap>: Sized {
294    type Out;
295}
296
297impl<Ctx, Cap> With<Cap> for Ctx
298where
299    Cap: Capability,
300    Ctx: InsertAt<Cap, D0>,
301{
302    type Out = <Ctx as InsertAt<Cap, D0>>::Out;
303}
304
305/// Remove a capability from a set (user-facing API)
306///
307/// This trait wraps `RemoveAt` with depth=D0 for a cleaner API.
308/// ```ignore
309/// type Reduced = <MySet as Without<CloneCap>>::Out;
310/// ```
311pub trait Without<Cap>: Sized {
312    type Out;
313}
314
315impl<Ctx, Cap> Without<Cap> for Ctx
316where
317    Cap: Capability,
318    Ctx: RemoveAt<Cap, D0>,
319{
320    type Out = <Ctx as RemoveAt<Cap, D0>>::Out;
321}