behavior/effects/
sending.rs1pub enum Own {}
5
6pub trait SendInput<Input, Path> {
16 fn emit(&mut self, input: Input);
17}
18
19pub trait SendAlgebra: Sized {
21 fn empty() -> Self;
22 fn append(&mut self, other: Self);
23
24 #[must_use]
25 fn combine(mut self, other: Self) -> Self {
26 self.append(other);
27 self
28 }
29
30 fn send<Input, Path>(&mut self, input: Input)
32 where
33 Self: SendInput<Input, Path>,
34 {
35 <Self as SendInput<Input, Path>>::emit(self, input);
36 }
37
38 #[must_use]
40 fn sending<Input, Path>(input: Input) -> Self
41 where
42 Self: SendInput<Input, Path>,
43 {
44 let mut sends = Self::empty();
45 sends.send(input);
46 sends
47 }
48}
49
50impl<T> SendAlgebra for Vec<T> {
51 fn empty() -> Self {
52 Vec::new()
53 }
54
55 fn append(&mut self, mut other: Self) {
56 Vec::append(self, &mut other);
57 }
58}
59
60impl<T> SendInput<T, Own> for Vec<T> {
61 fn emit(&mut self, input: T) {
62 self.push(input);
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct ServiceSends<M> {
74 requests: Vec<M>,
75}
76
77impl<M> ServiceSends<M> {
78 #[must_use]
79 pub fn new(requests: Vec<M>) -> Self {
80 Self { requests }
81 }
82 #[must_use]
83 pub fn one(request: M) -> Self {
84 Self::new(vec![request])
85 }
86 #[must_use]
87 pub fn as_slice(&self) -> &[M] {
88 &self.requests
89 }
90 pub fn iter(&self) -> core::slice::Iter<'_, M> {
91 self.requests.iter()
92 }
93 #[must_use]
94 pub fn len(&self) -> usize {
95 self.requests.len()
96 }
97 #[must_use]
98 pub fn is_empty(&self) -> bool {
99 self.requests.is_empty()
100 }
101 pub fn extend(&mut self, requests: impl IntoIterator<Item = M>) {
102 self.requests.extend(requests);
103 }
104 #[must_use]
105 pub fn into_requests(self) -> Vec<M> {
106 self.requests
107 }
108}
109
110impl<M> core::ops::Index<usize> for ServiceSends<M> {
111 type Output = M;
112 fn index(&self, index: usize) -> &Self::Output {
113 &self.requests[index]
114 }
115}
116
117impl<M> IntoIterator for ServiceSends<M> {
118 type Item = M;
119 type IntoIter = std::vec::IntoIter<M>;
120 fn into_iter(self) -> Self::IntoIter {
121 self.requests.into_iter()
122 }
123}
124
125impl<'a, M> IntoIterator for &'a ServiceSends<M> {
126 type Item = &'a M;
127 type IntoIter = core::slice::Iter<'a, M>;
128 fn into_iter(self) -> Self::IntoIter {
129 self.requests.iter()
130 }
131}
132
133impl<M> SendAlgebra for ServiceSends<M> {
134 fn empty() -> Self {
135 Self::new(Vec::new())
136 }
137 fn append(&mut self, mut other: Self) {
138 self.requests.append(&mut other.requests);
139 }
140}
141
142impl<M> SendInput<M, Own> for ServiceSends<M> {
143 fn emit(&mut self, input: M) {
144 self.requests.push(input);
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn send_algebra_obeys_identity_and_associativity() {
154 let values = vec![1, 2];
155 assert_eq!(Vec::new().combine(values.clone()), values);
156 assert_eq!(values.clone().combine(Vec::new()), values);
157
158 let left = vec![1].combine(vec![2]).combine(vec![3]);
159 let right = vec![1].combine(vec![2].combine(vec![3]));
160 assert_eq!(left, right);
161 }
162}