1use 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
12pub struct Has<Cap>(PhantomData<Cap>);
18
19pub struct And<L, R>(PhantomData<(L, R)>);
21
22pub struct Or<L, R>(PhantomData<(L, R)>);
24
25pub struct Not<Q>(PhantomData<Q>);
27
28pub struct HNil;
34
35pub struct HCons<H, T>(PhantomData<(H, T)>);
37
38pub struct All<List>(PhantomData<List>);
40
41pub struct Any<List>(PhantomData<List>);
43
44#[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 const RESULT: bool = <Self::Out as Bool>::VALUE;
60}
61
62pub 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
75use 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
100use 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#[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
122use super::node::Bucket;
132
133impl<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 }
146
147impl<Cap, Depth> EvalAt<Has<Cap>, Depth> for &Leaf<Cap>
150where
151 Cap: Capability,
152{
153 type Out = Present; }
155
156impl<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
169impl<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
178impl<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
187impl<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
196impl<Ctx> Evaluate<All<HNil>> for Ctx {
198 type Out = Present;
199}
200
201impl<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
210impl<Ctx> Evaluate<Any<HNil>> for Ctx {
212 type Out = Absent;
213}
214
215impl<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#[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
237pub 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#[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_export]
263macro_rules! all {
264 ($($item:ty),* $(,)?) => {
265 $crate::trie::All<hlist![$($item),*]>
266 };
267}
268
269#[macro_export]
271macro_rules! any {
272 ($($item:ty),* $(,)?) => {
273 $crate::trie::Any<hlist![$($item),*]>
274 };
275}