1use core::marker::PhantomData;
4
5pub enum Own {}
7
8pub struct Inner<Path>(PhantomData<fn(Path)>);
10
11pub trait SendInput<Input, Path> {
30 fn emit(&mut self, input: Input);
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct SendProduct<L, R> {
36 pub inner: L,
37 pub own: R,
38}
39
40impl<L, R> SendProduct<L, R> {
41 #[must_use]
42 pub const fn new(inner: L, own: R) -> Self {
43 Self { inner, own }
44 }
45
46 #[must_use]
47 pub fn split(self) -> (L, R) {
48 (self.inner, self.own)
49 }
50}
51
52impl<L, R> From<(L, R)> for SendProduct<L, R> {
53 fn from((inner, own): (L, R)) -> Self {
54 Self::new(inner, own)
55 }
56}
57
58pub trait SendAlgebra: Sized {
60 fn empty() -> Self;
61 fn append(&mut self, other: Self);
62
63 #[must_use]
64 fn combine(mut self, other: Self) -> Self {
65 self.append(other);
66 self
67 }
68
69 fn send<Input, Path>(&mut self, input: Input)
71 where
72 Self: SendInput<Input, Path>,
73 {
74 <Self as SendInput<Input, Path>>::emit(self, input);
75 }
76
77 #[must_use]
79 fn sending<Input, Path>(input: Input) -> Self
80 where
81 Self: SendInput<Input, Path>,
82 {
83 let mut sends = Self::empty();
84 sends.send(input);
85 sends
86 }
87}
88
89impl<T> SendAlgebra for Vec<T> {
90 fn empty() -> Self {
91 Vec::new()
92 }
93
94 fn append(&mut self, mut other: Self) {
95 Vec::append(self, &mut other);
96 }
97}
98
99impl<T> SendInput<T, Own> for Vec<T> {
100 fn emit(&mut self, input: T) {
101 self.push(input);
102 }
103}
104
105impl<L, R, Input> SendInput<Input, Own> for SendProduct<L, R>
106where
107 R: SendInput<Input, Own>,
108{
109 fn emit(&mut self, input: Input) {
110 <R as SendInput<Input, Own>>::emit(&mut self.own, input);
111 }
112}
113
114impl<L, R, Input, Path> SendInput<Input, Inner<Path>> for SendProduct<L, R>
115where
116 L: SendInput<Input, Path>,
117{
118 fn emit(&mut self, input: Input) {
119 <L as SendInput<Input, Path>>::emit(&mut self.inner, input);
120 }
121}
122
123impl<L: SendAlgebra, R: SendAlgebra> SendAlgebra for SendProduct<L, R> {
124 fn empty() -> Self {
125 Self::new(L::empty(), R::empty())
126 }
127
128 fn append(&mut self, other: Self) {
129 let (inner, own) = other.split();
130 self.inner.append(inner);
131 self.own.append(own);
132 }
133}
134
135#[derive(Debug, Clone, PartialEq, Eq)]
142pub struct ServiceSends<M> {
143 requests: Vec<M>,
144}
145
146impl<M> ServiceSends<M> {
147 #[must_use]
148 pub fn new(requests: Vec<M>) -> Self {
149 Self { requests }
150 }
151 #[must_use]
152 pub fn one(request: M) -> Self {
153 Self::new(vec![request])
154 }
155 #[must_use]
156 pub fn as_slice(&self) -> &[M] {
157 &self.requests
158 }
159 pub fn iter(&self) -> core::slice::Iter<'_, M> {
160 self.requests.iter()
161 }
162 #[must_use]
163 pub fn len(&self) -> usize {
164 self.requests.len()
165 }
166 #[must_use]
167 pub fn is_empty(&self) -> bool {
168 self.requests.is_empty()
169 }
170 pub fn extend(&mut self, requests: impl IntoIterator<Item = M>) {
171 self.requests.extend(requests);
172 }
173 #[must_use]
174 pub fn into_requests(self) -> Vec<M> {
175 self.requests
176 }
177}
178
179impl<M> core::ops::Index<usize> for ServiceSends<M> {
180 type Output = M;
181 fn index(&self, index: usize) -> &Self::Output {
182 &self.requests[index]
183 }
184}
185
186impl<M> IntoIterator for ServiceSends<M> {
187 type Item = M;
188 type IntoIter = std::vec::IntoIter<M>;
189 fn into_iter(self) -> Self::IntoIter {
190 self.requests.into_iter()
191 }
192}
193
194impl<'a, M> IntoIterator for &'a ServiceSends<M> {
195 type Item = &'a M;
196 type IntoIter = core::slice::Iter<'a, M>;
197 fn into_iter(self) -> Self::IntoIter {
198 self.requests.iter()
199 }
200}
201
202impl<M> SendAlgebra for ServiceSends<M> {
203 fn empty() -> Self {
204 Self::new(Vec::new())
205 }
206 fn append(&mut self, mut other: Self) {
207 self.requests.append(&mut other.requests);
208 }
209}
210
211impl<M> SendInput<M, Own> for ServiceSends<M> {
212 fn emit(&mut self, input: M) {
213 self.requests.push(input);
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use proptest::prelude::*;
221
222 #[test]
223 fn send_algebra_obeys_identity_and_associativity() {
224 let values = vec![1, 2];
225 assert_eq!(Vec::new().combine(values.clone()), values);
226 assert_eq!(values.clone().combine(Vec::new()), values);
227
228 let left = vec![1].combine(vec![2]).combine(vec![3]);
229 let right = vec![1].combine(vec![2].combine(vec![3]));
230 assert_eq!(left, right);
231 }
232
233 #[test]
234 fn typed_paths_select_exactly_one_product_lane() {
235 type Sends = SendProduct<SendProduct<Vec<u8>, Vec<u16>>, Vec<u32>>;
236
237 let mut sends = Sends::empty();
238 sends.send::<_, Inner<Inner<Own>>>(1_u8);
239 sends.send::<_, Inner<Own>>(2_u16);
240 sends.send::<_, Own>(3_u32);
241
242 assert_eq!(sends.inner.inner, vec![1]);
243 assert_eq!(sends.inner.own, vec![2]);
244 assert_eq!(sends.own, vec![3]);
245 }
246
247 proptest! {
248 #[test]
249 fn typed_path_emission_preserves_every_unselected_lane(
250 inner in proptest::collection::vec(any::<u8>(), 0..16),
251 middle in proptest::collection::vec(any::<u16>(), 0..16),
252 own in proptest::collection::vec(any::<u32>(), 0..16),
253 input in any::<u16>(),
254 ) {
255 let original_inner = inner.clone();
256 let original_own = own.clone();
257 let mut sends = SendProduct::new(SendProduct::new(inner, middle.clone()), own);
258
259 sends.send::<_, Inner<Own>>(input);
260
261 prop_assert_eq!(sends.inner.inner, original_inner);
262 prop_assert_eq!(sends.inner.own.len(), middle.len() + 1);
263 prop_assert_eq!(&sends.inner.own[..middle.len()], middle.as_slice());
264 prop_assert_eq!(sends.inner.own.last(), Some(&input));
265 prop_assert_eq!(sends.own, original_own);
266 }
267 }
268}