Skip to main content

interstice_sdk_core/
caps.rs

1//! Capability markers (`ReadFoo`, …) from `#[table]` and tuple composition for context generics.
2//!
3//! [`ReducerCaps`] / [`QueryCaps`] compose for nested pairs `(A, B)` and recurse for schema.
4//! [`CanRead`] / [`CanInsert`] / [`CanUpdate`] / [`CanDelete`] do **not** infer through `(A, B)` (Rust
5//! cannot express “either side” without overlapping impls). For multi-table reducer caps, use a
6//! module-local zero-sized struct and implement the needed `Can*` markers per row type (often via a
7//! small declarative macro in your crate), delegating [`ReducerCaps::extend_reducer_schema`] to a
8//! nested tuple of `Read*` / `Insert*` / … markers.
9
10use interstice_abi::ReducerTableRef;
11
12/// Read access to rows of type `Row` (the `#[table]` struct).
13pub trait CanRead<Row> {}
14/// Insert access for `Row`.
15pub trait CanInsert<Row> {}
16/// Update access for `Row`.
17pub trait CanUpdate<Row> {}
18/// Delete access for `Row`.
19pub trait CanDelete<Row> {}
20
21/// One leaf of a reducer `Caps` tree: contributes [`ReducerTableRef`] entries.
22pub trait ReducerCapPiece {
23    fn extend_reducer_schema(
24        reads: &mut Vec<ReducerTableRef>,
25        inserts: &mut Vec<ReducerTableRef>,
26        updates: &mut Vec<ReducerTableRef>,
27        deletes: &mut Vec<ReducerTableRef>,
28    );
29}
30
31/// Composed reducer capabilities (markers, tuples, or `()`).
32pub trait ReducerCaps {
33    fn extend_reducer_schema(
34        reads: &mut Vec<ReducerTableRef>,
35        inserts: &mut Vec<ReducerTableRef>,
36        updates: &mut Vec<ReducerTableRef>,
37        deletes: &mut Vec<ReducerTableRef>,
38    );
39}
40
41impl ReducerCaps for () {
42    fn extend_reducer_schema(
43        _reads: &mut Vec<ReducerTableRef>,
44        _inserts: &mut Vec<ReducerTableRef>,
45        _updates: &mut Vec<ReducerTableRef>,
46        _deletes: &mut Vec<ReducerTableRef>,
47    ) {
48    }
49}
50
51impl<T: ReducerCapPiece> ReducerCaps for T {
52    fn extend_reducer_schema(
53        reads: &mut Vec<ReducerTableRef>,
54        inserts: &mut Vec<ReducerTableRef>,
55        updates: &mut Vec<ReducerTableRef>,
56        deletes: &mut Vec<ReducerTableRef>,
57    ) {
58        T::extend_reducer_schema(reads, inserts, updates, deletes);
59    }
60}
61
62impl<A: ReducerCaps, B: ReducerCaps> ReducerCaps for (A, B) {
63    fn extend_reducer_schema(
64        reads: &mut Vec<ReducerTableRef>,
65        inserts: &mut Vec<ReducerTableRef>,
66        updates: &mut Vec<ReducerTableRef>,
67        deletes: &mut Vec<ReducerTableRef>,
68    ) {
69        A::extend_reducer_schema(reads, inserts, updates, deletes);
70        B::extend_reducer_schema(reads, inserts, updates, deletes);
71    }
72}
73
74impl<A: ReducerCaps> ReducerCaps for (A,) {
75    fn extend_reducer_schema(
76        reads: &mut Vec<ReducerTableRef>,
77        inserts: &mut Vec<ReducerTableRef>,
78        updates: &mut Vec<ReducerTableRef>,
79        deletes: &mut Vec<ReducerTableRef>,
80    ) {
81        A::extend_reducer_schema(reads, inserts, updates, deletes);
82    }
83}
84
85/// One leaf of a query `Caps` tree.
86pub trait QueryCapPiece {
87    fn extend_query_schema(reads: &mut Vec<ReducerTableRef>);
88}
89
90pub trait QueryCaps {
91    fn extend_query_schema(reads: &mut Vec<ReducerTableRef>);
92}
93
94impl QueryCaps for () {
95    fn extend_query_schema(_reads: &mut Vec<ReducerTableRef>) {}
96}
97
98impl<T: QueryCapPiece> QueryCaps for T {
99    fn extend_query_schema(reads: &mut Vec<ReducerTableRef>) {
100        T::extend_query_schema(reads);
101    }
102}
103
104impl<A: QueryCaps, B: QueryCaps> QueryCaps for (A, B) {
105    fn extend_query_schema(reads: &mut Vec<ReducerTableRef>) {
106        A::extend_query_schema(reads);
107        B::extend_query_schema(reads);
108    }
109}
110
111impl<A: QueryCaps> QueryCaps for (A,) {
112    fn extend_query_schema(reads: &mut Vec<ReducerTableRef>) {
113        A::extend_query_schema(reads);
114    }
115}
116
117/// Single-field tuple wrapper delegates to the inner marker (see module-level docs for composition).
118macro_rules! impl_disjunctive_can {
119    ($trait:ident) => {
120        impl<Row, A> $trait<Row> for (A,) where A: $trait<Row> {}
121    };
122}
123
124impl_disjunctive_can!(CanRead);
125impl_disjunctive_can!(CanInsert);
126impl_disjunctive_can!(CanUpdate);
127impl_disjunctive_can!(CanDelete);