Skip to main content

ruststream_sqlx/inbox/spec/
declaration.rs

1//! The settings of a table as one type: each marker sets one slot, a tuple folds its markers slot
2//! by slot, and a slot set twice has no fold.
3
4pub use crate::settings::{Merge, Push, Set, Unset};
5
6/// The settings of a table, one associated type per setting: [`Unset`] where the table keeps the
7/// default, [`Set`] with the marker that sets it otherwise.
8///
9/// Each marker of [`spec`](crate::spec) is one, and so is a tuple of them.
10pub trait Declaration {
11    /// The form: [`Lease`](super::Lease) or [`Advisory`](super::Advisory); unset for the row lock
12    /// form.
13    type Form;
14    /// The message mode: [`Payload`](super::Payload); unset for row mode.
15    type Message;
16    /// The partition key: [`Key`](super::Key).
17    type Key;
18    /// The attempt count: [`Attempt`](super::Attempt).
19    type Attempt;
20    /// The delivery's headers: [`Headers`](super::Headers) or
21    /// [`HeaderFields`](super::HeaderFields).
22    type Headers;
23    /// The time a retried row is due: [`RetryAfter`](super::RetryAfter).
24    type RetryAfter;
25    /// The time a row was processed: [`ProcessedAt`](super::ProcessedAt).
26    type ProcessedAt;
27    /// The clock: [`Clock`](super::Clock); unset for [`SystemClock`](crate::SystemClock).
28    type Clock;
29    /// What the table's transactions open at: [`Opens`](super::Opens); unset for the database's
30    /// default.
31    type Opening;
32    /// Groups kept in order: [`Fifo`](super::Fifo).
33    type Fifo;
34    /// The service's own claim: [`own::Claim`](super::own::Claim).
35    type OwnClaim;
36    /// The service's own fetch: [`own::Fetch`](super::own::Fetch).
37    type OwnFetch;
38    /// The service's own ack: [`own::Ack`](super::own::Ack).
39    type OwnAck;
40    /// The service's own retry: [`own::Retry`](super::own::Retry).
41    type OwnRetry;
42    /// The service's own delayed retry: [`own::RetryAfter`](super::own::RetryAfter).
43    type OwnRetryAfter;
44    /// The service's own discard: [`own::Discard`](super::own::Discard).
45    type OwnDiscard;
46    /// The service's own dead letter: [`own::DeadLetter`](super::own::DeadLetter).
47    type OwnDeadLetter;
48    /// The service's own lease extension: [`own::Extend`](super::own::Extend).
49    type OwnExtend;
50    /// The service's own lock: [`own::Lock`](super::own::Lock).
51    type OwnLock;
52    /// The service's own unlock: [`own::Unlock`](super::own::Unlock).
53    type OwnUnlock;
54}
55
56/// One marker: it sets its own slot to itself and leaves every other slot unset.
57macro_rules! setting {
58    ($(#[$doc:meta])* $name:ident $(<$param:ident>)?, $slot:ident) => {
59        $(#[$doc])*
60        #[derive(Debug)]
61        pub struct $name$(<$param>(PhantomData<fn() -> $param>))?;
62
63        impl$(<$param>)? Declaration for $name$(<$param>)? {
64            setting!(@slots $slot, Set<Self>;
65                Form Message Key Attempt Headers RetryAfter ProcessedAt Clock Opening Fifo
66                OwnClaim OwnFetch OwnAck OwnRetry OwnRetryAfter OwnDiscard OwnDeadLetter
67                OwnExtend OwnLock OwnUnlock);
68        }
69    };
70    (@slots $slot:ident, $value:ty; $($each:ident)*) => {
71        $(setting!(@slot $slot, $value; $each);)*
72    };
73    (@slot Form, $value:ty; Form) => { type Form = $value; };
74    (@slot Message, $value:ty; Message) => { type Message = $value; };
75    (@slot Key, $value:ty; Key) => { type Key = $value; };
76    (@slot Attempt, $value:ty; Attempt) => { type Attempt = $value; };
77    (@slot Headers, $value:ty; Headers) => { type Headers = $value; };
78    (@slot RetryAfter, $value:ty; RetryAfter) => { type RetryAfter = $value; };
79    (@slot ProcessedAt, $value:ty; ProcessedAt) => { type ProcessedAt = $value; };
80    (@slot Clock, $value:ty; Clock) => { type Clock = $value; };
81    (@slot Opening, $value:ty; Opening) => { type Opening = $value; };
82    (@slot Fifo, $value:ty; Fifo) => { type Fifo = $value; };
83    (@slot OwnClaim, $value:ty; OwnClaim) => { type OwnClaim = $value; };
84    (@slot OwnFetch, $value:ty; OwnFetch) => { type OwnFetch = $value; };
85    (@slot OwnAck, $value:ty; OwnAck) => { type OwnAck = $value; };
86    (@slot OwnRetry, $value:ty; OwnRetry) => { type OwnRetry = $value; };
87    (@slot OwnRetryAfter, $value:ty; OwnRetryAfter) => { type OwnRetryAfter = $value; };
88    (@slot OwnDiscard, $value:ty; OwnDiscard) => { type OwnDiscard = $value; };
89    (@slot OwnDeadLetter, $value:ty; OwnDeadLetter) => { type OwnDeadLetter = $value; };
90    (@slot OwnExtend, $value:ty; OwnExtend) => { type OwnExtend = $value; };
91    (@slot OwnLock, $value:ty; OwnLock) => { type OwnLock = $value; };
92    (@slot OwnUnlock, $value:ty; OwnUnlock) => { type OwnUnlock = $value; };
93    (@slot $slot:ident, $value:ty; $other:ident) => { type $other = Unset; };
94}
95
96pub(super) use setting;
97
98impl Declaration for () {
99    type Form = Unset;
100    type Message = Unset;
101    type Key = Unset;
102    type Attempt = Unset;
103    type Headers = Unset;
104    type RetryAfter = Unset;
105    type ProcessedAt = Unset;
106    type Clock = Unset;
107    type Opening = Unset;
108    type Fifo = Unset;
109    type OwnClaim = Unset;
110    type OwnFetch = Unset;
111    type OwnAck = Unset;
112    type OwnRetry = Unset;
113    type OwnRetryAfter = Unset;
114    type OwnDiscard = Unset;
115    type OwnDeadLetter = Unset;
116    type OwnExtend = Unset;
117    type OwnLock = Unset;
118    type OwnUnlock = Unset;
119}
120
121/// A tuple of markers folds its head into the declaration of its tail, slot by slot.
122macro_rules! tuple {
123    ($head:ident $(, $tail:ident)*) => {
124        tuple!(@impl [$head $(, $tail)*] $head, ($($tail,)*);
125            Form Message Key Attempt Headers RetryAfter ProcessedAt Clock Opening Fifo
126            OwnClaim OwnFetch OwnAck OwnRetry OwnRetryAfter OwnDiscard OwnDeadLetter
127            OwnExtend OwnLock OwnUnlock);
128    };
129    (@impl [$($each:ident),*] $head:ident, $tail:ty; $($slot:ident)*) => {
130        impl<$($each: Declaration),*> Declaration for ($($each,)*)
131        where
132            $tail: Declaration,
133            $($head::$slot: Merge<<$tail as Declaration>::$slot>,)*
134        {
135            $(type $slot = <$head::$slot as Merge<<$tail as Declaration>::$slot>>::Out;)*
136        }
137    };
138}
139
140tuple!(Setting1);
141tuple!(Setting1, Setting2);
142tuple!(Setting1, Setting2, Setting3);
143tuple!(Setting1, Setting2, Setting3, Setting4);
144tuple!(Setting1, Setting2, Setting3, Setting4, Setting5);
145tuple!(Setting1, Setting2, Setting3, Setting4, Setting5, Setting6);
146tuple!(
147    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7
148);
149tuple!(
150    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8
151);
152tuple!(
153    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9
154);
155tuple!(
156    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
157    Setting10
158);
159tuple!(
160    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
161    Setting10, Setting11
162);
163tuple!(
164    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
165    Setting10, Setting11, Setting12
166);
167tuple!(
168    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
169    Setting10, Setting11, Setting12, Setting13
170);
171tuple!(
172    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
173    Setting10, Setting11, Setting12, Setting13, Setting14
174);
175tuple!(
176    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
177    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15
178);
179tuple!(
180    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
181    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15, Setting16
182);
183tuple!(
184    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
185    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15, Setting16, Setting17
186);
187tuple!(
188    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
189    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15, Setting16, Setting17,
190    Setting18
191);
192tuple!(
193    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
194    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15, Setting16, Setting17,
195    Setting18, Setting19
196);
197tuple!(
198    Setting1, Setting2, Setting3, Setting4, Setting5, Setting6, Setting7, Setting8, Setting9,
199    Setting10, Setting11, Setting12, Setting13, Setting14, Setting15, Setting16, Setting17,
200    Setting18, Setting19, Setting20
201);
202
203#[cfg(test)]
204mod tests {
205    use std::any::TypeId;
206    use std::time::SystemTime;
207
208    use super::{Declaration, Set, Unset};
209    use crate::SystemClock;
210    use crate::inbox::spec::{
211        Attempt, Clock, Fifo, Headers, Key, Lease, Payload, ProcessedAt, RetryAfter, own,
212    };
213
214    /// Whether two types are one.
215    fn same<Left: 'static, Right: 'static>() -> bool {
216        TypeId::of::<Left>() == TypeId::of::<Right>()
217    }
218
219    #[test]
220    fn a_lease_table_folds_each_setting_into_its_own_slot() {
221        type Settings = (
222            Lease<SystemTime>,
223            Payload,
224            Attempt,
225            RetryAfter<SystemTime>,
226            ProcessedAt<SystemTime>,
227            Key,
228        );
229        assert!(same::<
230            <Settings as Declaration>::Form,
231            Set<Lease<SystemTime>>,
232        >());
233        assert!(same::<<Settings as Declaration>::Message, Set<Payload>>());
234        assert!(same::<<Settings as Declaration>::Key, Set<Key>>());
235        assert!(same::<<Settings as Declaration>::Attempt, Set<Attempt>>());
236        assert!(same::<
237            <Settings as Declaration>::RetryAfter,
238            Set<RetryAfter<SystemTime>>,
239        >());
240        assert!(same::<
241            <Settings as Declaration>::ProcessedAt,
242            Set<ProcessedAt<SystemTime>>,
243        >());
244        assert!(same::<<Settings as Declaration>::Headers, Unset>());
245        assert!(same::<<Settings as Declaration>::Clock, Unset>());
246        assert!(same::<<Settings as Declaration>::OwnAck, Unset>());
247    }
248
249    #[test]
250    fn an_own_event_folds_into_its_own_slot() {
251        type Settings = (Fifo, Headers, own::Ack, Clock<SystemClock>);
252        assert!(same::<<Settings as Declaration>::OwnAck, Set<own::Ack>>());
253        assert!(same::<<Settings as Declaration>::Fifo, Set<Fifo>>());
254        assert!(same::<<Settings as Declaration>::OwnClaim, Unset>());
255        assert!(same::<<Settings as Declaration>::Form, Unset>());
256    }
257}