1use std::collections::HashMap ;
4use std::future::Future ;
5use std::hash::Hash ;
6
7use futures::future::{ BoxFuture, join_all };
8use nonempty_collections::{ NEMap, NonEmptyIterator, IntoNonEmptyIterator };
9use wasmtime::component::Val ;
10
11
12
13pub trait Cardinality<Id, T>: Sized {
18 type Rebind<U>;
20
21 fn map<N>( &self, map: impl FnMut( &Id, &T ) -> N ) -> Self::Rebind<N>
23 where
24 Id: Clone;
25
26 fn map_mut<N>( self, map: impl FnMut( T ) -> N ) -> Self::Rebind<N> ;
28
29 fn map_async<'a, N, F, Fut>( &'a self, map: F ) -> BoxFuture<'a, Self::Rebind<N>>
45 where
46 Id: Clone + Send + 'a,
47 T: Clone + Send + 'a,
48 N: Send + 'a,
49 F: Fn( Id, T ) -> Fut + Send + 'a,
50 Fut: Future<Output = N> + Send + 'a;
51
52 fn get( &self, id: &Id ) -> Option<&T>
54 where
55 Id: Hash + Eq ;
56}
57
58#[derive( Debug, Clone )]
60pub struct ExactlyOne<Id, T>(
61 pub Id,
63 pub T
65);
66
67#[derive( Debug, Clone )]
69pub struct AtMostOne<Id, T>(
70 pub Option<( Id, T )>
72);
73
74#[derive( Debug, Clone )]
76pub struct AtLeastOne<Id, T>(
77 pub NEMap<Id, T>
79);
80
81#[derive( Debug, Clone )]
83pub struct Any<Id, T>(
84 pub HashMap<Id, T>
86);
87
88impl<Id, T> Cardinality<Id, T> for ExactlyOne<Id, T> {
89 type Rebind<U> = ExactlyOne<Id, U>;
90
91 fn map<N>( &self, mut map: impl FnMut( &Id, &T ) -> N ) -> Self::Rebind<N>
92 where
93 Id: Clone,
94 {
95 ExactlyOne( self.0.clone(), map( &self.0, &self.1 ))
96 }
97
98 fn map_mut<N>( self, mut map: impl FnMut( T ) -> N ) -> Self::Rebind<N> {
99 ExactlyOne( self.0, map( self.1 ))
100 }
101
102 fn map_async<'a, N, F, Fut>( &'a self, map: F ) -> BoxFuture<'a, Self::Rebind<N>>
103 where
104 Id: Clone + Send + 'a,
105 T: Clone + Send + 'a,
106 N: Send + 'a,
107 F: Fn( Id, T ) -> Fut + Send + 'a,
108 Fut: Future<Output = N> + Send + 'a,
109 {
110 let id = self.0.clone();
111 let value = self.1.clone();
112 Box::pin( async move {
113 let mapped = map( id.clone(), value ).await;
114 ExactlyOne( id, mapped )
115 })
116 }
117
118 fn get( &self, id: &Id ) -> Option<&T>
119 where
120 Id: Hash + Eq,
121 {
122 debug_assert!( &self.0 == id, "singleton cardinality id mismatch" );
125 Some( &self.1 )
126 }
127}
128
129impl<Id, T> Cardinality<Id, T> for AtMostOne<Id, T> {
130 type Rebind<U> = AtMostOne<Id, U>;
131
132 fn map<N>( &self, mut map: impl FnMut( &Id, &T ) -> N ) -> Self::Rebind<N>
133 where
134 Id: Clone,
135 {
136 match &self.0 {
137 None => AtMostOne( None ),
138 Some(( id, value )) => AtMostOne( Some(( id.clone(), map( id, value )))),
139 }
140 }
141
142 fn map_mut<N>( self, mut map: impl FnMut( T ) -> N ) -> Self::Rebind<N> {
143 match self.0 {
144 None => AtMostOne( None ),
145 Some(( id, value )) => AtMostOne( Some(( id, map( value )))),
146 }
147 }
148
149 fn map_async<'a, N, F, Fut>( &'a self, map: F ) -> BoxFuture<'a, Self::Rebind<N>>
150 where
151 Id: Clone + Send + 'a,
152 T: Clone + Send + 'a,
153 N: Send + 'a,
154 F: Fn( Id, T ) -> Fut + Send + 'a,
155 Fut: Future<Output = N> + Send + 'a,
156 {
157 let value = self.0.clone();
158 Box::pin( async move { match value {
159 None => AtMostOne( None ),
160 Some(( id, value )) => {
161 let mapped = map( id.clone(), value ).await;
162 AtMostOne( Some(( id, mapped )))
163 }
164 }})
165 }
166
167 fn get( &self, id: &Id ) -> Option<&T>
168 where
169 Id: Hash + Eq,
170 {
171 match self.0.as_ref() {
172 None => None,
173 Some(( stored_id, value )) => {
174 debug_assert!( stored_id == id, "singleton cardinality id mismatch" );
177 Some( value )
178 }
179 }
180 }
181}
182
183impl<Id: Hash + Eq, T> Cardinality<Id, T> for AtLeastOne<Id, T> {
184 type Rebind<U> = AtLeastOne<Id, U>;
185
186 fn map<N>( &self, mut map: impl FnMut( &Id, &T ) -> N ) -> Self::Rebind<N>
187 where
188 Id: Clone,
189 {
190 AtLeastOne(
191 self.0.nonempty_iter()
192 .map(|( id, value )| ( id.clone(), map( id, value )))
193 .collect()
194 )
195 }
196
197 fn map_mut<N>( self, mut map: impl FnMut( T ) -> N ) -> Self::Rebind<N> {
198 AtLeastOne(
199 self.0.into_nonempty_iter()
200 .map(|( id, value )| ( id, map( value )))
201 .collect()
202 )
203 }
204
205 fn map_async<'a, N, F, Fut>( &'a self, map: F ) -> BoxFuture<'a, Self::Rebind<N>>
206 where
207 Id: Clone + Send + 'a,
208 T: Clone + Send + 'a,
209 N: Send + 'a,
210 F: Fn( Id, T ) -> Fut + Send + 'a,
211 Fut: Future<Output = N> + Send + 'a,
212 {
213 let entries = self.0.nonempty_iter()
214 .map(|( id, value )| ( id.clone(), value.clone() ))
215 .collect::<Vec<_>>();
216 Box::pin( async move {
217 let mut mapped_values = join_all( entries.into_iter().map(|( id, value )| {
218 let future = map( id.clone(), value );
219 async move { ( id, future.await ) }
220 })).await.into_iter();
221 let Some(( first_id, first_mapped )) = mapped_values.next() else { unreachable!() };
222 let mut mapped = NEMap::new( first_id, first_mapped );
223 mapped.extend( mapped_values );
224 AtLeastOne( mapped )
225 })
226 }
227
228 fn get( &self, id: &Id ) -> Option<&T>
229 where
230 Id: Hash + Eq,
231 {
232 self.0.get( id )
233 }
234}
235
236impl<Id: Hash + Eq, T> Cardinality<Id, T> for Any<Id, T> {
237 type Rebind<U> = Any<Id, U>;
238
239 fn map<N>( &self, mut map: impl FnMut( &Id, &T ) -> N ) -> Self::Rebind<N>
240 where
241 Id: Clone,
242 {
243 Any( self.0.iter().map(|( id, value )| ( id.clone(), map( id, value ))).collect() )
244 }
245
246 fn map_mut<N>( self, mut map: impl FnMut( T ) -> N ) -> Self::Rebind<N> {
247 Any( self.0.into_iter().map(|( id, value )| ( id, map( value ))).collect() )
248 }
249
250 fn map_async<'a, N, F, Fut>( &'a self, map: F ) -> BoxFuture<'a, Self::Rebind<N>>
251 where
252 Id: Clone + Send + 'a,
253 T: Clone + Send + 'a,
254 N: Send + 'a,
255 F: Fn( Id, T ) -> Fut + Send + 'a,
256 Fut: Future<Output = N> + Send + 'a,
257 {
258 let entries = self.0.iter().map(|( id, value )| ( id.clone(), value.clone() )).collect::<Vec<_>>();
259 Box::pin( async move {
260 Any( join_all( entries.into_iter().map(|( id, value )| {
261 let future = map( id.clone(), value );
262 async move { ( id, future.await ) }
263 })).await.into_iter().collect() )
264 })
265 }
266
267 fn get( &self, id: &Id ) -> Option<&T>
268 where
269 Id: Hash + Eq,
270 {
271 self.0.get( id )
272 }
273}
274
275impl<Id: Hash + Eq + Into<Val>> From<ExactlyOne<Id, Val>> for Val {
276 fn from( socket: ExactlyOne<Id, Val> ) -> Self {
277 Val::Tuple( vec![ socket.0.into(), socket.1 ])
278 }
279}
280
281impl<Id: Hash + Eq + Into<Val>> From<AtMostOne<Id, Val>> for Val {
282 fn from( socket: AtMostOne<Id, Val> ) -> Self {
283 match socket.0 {
284 None => Val::Option( None ),
285 Some(( id, val )) => Val::Option( Some( Box::new( Val::Tuple( vec![ id.into(), val ] )))),
286 }
287 }
288}
289
290impl<Id: Hash + Eq + Into<Val>> From<AtLeastOne<Id, Val>> for Val {
291 fn from( socket: AtLeastOne<Id, Val> ) -> Self {
292 Val::Map(
293 socket.0.into_iter()
294 .map(|( id, val )| ( id.into(), val ))
295 .collect()
296 )
297 }
298}
299
300impl<Id: Hash + Eq + Into<Val>> From<Any<Id, Val>> for Val {
301 fn from( socket: Any<Id, Val> ) -> Self {
302 Val::Map(
303 socket.0.into_iter()
304 .map(|( id, val )| ( id.into(), val ))
305 .collect()
306 )
307 }
308}