1use super::{
6 CanonicalRelationPosition, KeyedRosterRelation, KeyedRosterRows, KeyedRosterRowsError,
7 ReferencedRosterRow, RelationPair, RepeatedRelationPair, RepeatedRelationPairs,
8 ResolvedRosterMember, RowResolutionError,
9};
10use crate::bounded::{Bounded, ForeignRosterReference, KeyedRoster, NonEmpty, NonEmptyError};
11use core::borrow::Borrow;
12
13impl<
14 'rosters,
15 Left,
16 LeftKey,
17 Right,
18 RightKey,
19 Payload,
20 const LEFT: usize,
21 const RIGHT: usize,
22 const ROWS: usize,
23> KeyedRosterRows<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>
24{
25 #[must_use]
27 pub const fn left(&self) -> &'rosters KeyedRoster<Left, LeftKey, LEFT> {
28 self.left
29 }
30
31 #[must_use]
33 pub const fn right(&self) -> &'rosters KeyedRoster<Right, RightKey, RIGHT> {
34 self.right
35 }
36
37 #[must_use]
39 pub fn count(&self) -> usize {
40 self.rows.len()
41 }
42
43 #[must_use]
45 pub fn is_empty(&self) -> bool {
46 self.rows.is_empty()
47 }
48
49 pub fn indexed(
51 &self,
52 ) -> impl Iterator<Item = (usize, &LeftKey, &Left, &RightKey, &Right, &Payload)> {
53 self.rows.iter().enumerate().map(|(index, row)| {
54 (
55 index,
56 row.left_key,
57 row.left_member,
58 row.right_key,
59 row.right_member,
60 &row.payload,
61 )
62 })
63 }
64
65 #[must_use]
67 pub fn at(&self, index: usize) -> Option<(&LeftKey, &Left, &RightKey, &Right, &Payload)> {
68 self.rows.as_slice().get(index).map(|row| {
69 (
70 row.left_key,
71 row.left_member,
72 row.right_key,
73 row.right_member,
74 &row.payload,
75 )
76 })
77 }
78
79 #[must_use]
83 pub fn canonical_indices(&self) -> &[usize] {
84 self.canonical_indices.as_slice()
85 }
86
87 #[must_use]
89 pub fn canonical_at(
90 &self,
91 index: usize,
92 ) -> Option<(&LeftKey, &Left, &RightKey, &Right, &Payload)> {
93 self.canonical_indices()
94 .get(index)
95 .and_then(|authored| self.at(*authored))
96 }
97
98 pub fn payloads_for<'reading, LeftQuery, RightQuery>(
100 &'reading self,
101 left: &LeftQuery,
102 right: &RightQuery,
103 ) -> impl Iterator<Item = &'reading Payload>
104 where
105 LeftKey: Borrow<LeftQuery>,
106 LeftQuery: Eq + ?Sized,
107 RightKey: Borrow<RightQuery>,
108 RightQuery: Eq + ?Sized,
109 {
110 let left_position = self.left.index_of(left);
111 let right_position = self.right.index_of(right);
112 self.rows.iter().filter_map(move |row| {
113 (Some(row.left_position) == left_position && Some(row.right_position) == right_position)
114 .then_some(&row.payload)
115 })
116 }
117
118 pub fn distinct(
124 self,
125 ) -> Result<
126 KeyedRosterRelation<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>,
127 RepeatedRelationPairs<ROWS>,
128 > {
129 match repeated_relation_pairs(&self) {
130 Some(repeated) => Err(repeated),
131 None => Ok(KeyedRosterRelation { rows: self }),
132 }
133 }
134}
135
136impl<
137 'rosters,
138 Left,
139 LeftKey: Eq,
140 Right,
141 RightKey: Eq,
142 Payload,
143 const LEFT: usize,
144 const RIGHT: usize,
145 const ROWS: usize,
146> KeyedRosterRows<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>
147{
148 pub fn referenced(
157 left: &'rosters KeyedRoster<Left, LeftKey, LEFT>,
158 right: &'rosters KeyedRoster<Right, RightKey, RIGHT>,
159 payloads: Vec<Payload>,
160 left_key_of: impl FnMut(&Payload) -> LeftKey,
161 right_key_of: impl FnMut(&Payload) -> RightKey,
162 ) -> Result<Self, KeyedRosterRowsError<LeftKey, RightKey, ROWS>> {
163 let payloads = Bounded::new(payloads).map_err(KeyedRosterRowsError::Overflow)?;
164 let left_rows = resolve_rows(left, &payloads, left_key_of).map_err(left_refusal)?;
165 let right_rows = resolve_rows(right, &payloads, right_key_of).map_err(right_refusal)?;
166 let rows = payloads
167 .into_vec()
168 .into_iter()
169 .zip(left_rows)
170 .zip(right_rows)
171 .map(row_from_resolved)
172 .collect::<Vec<_>>();
173 let rows = Bounded::new(rows).map_err(KeyedRosterRowsError::Overflow)?;
174 let canonical_indices = canonical_indices(&rows)?;
175 Ok(Self {
176 left,
177 right,
178 rows,
179 canonical_indices,
180 })
181 }
182}
183
184impl<
185 'rosters,
186 Left,
187 LeftKey,
188 Right,
189 RightKey,
190 Payload,
191 const LEFT: usize,
192 const RIGHT: usize,
193 const ROWS: usize,
194> KeyedRosterRelation<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>
195{
196 #[must_use]
198 pub const fn rows(
199 &self,
200 ) -> &KeyedRosterRows<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>
201 {
202 &self.rows
203 }
204
205 #[must_use]
207 pub fn into_rows(
208 self,
209 ) -> KeyedRosterRows<'rosters, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS> {
210 self.rows
211 }
212}
213
214impl<const N: usize> RepeatedRelationPair<N> {
215 #[must_use]
217 pub const fn left_position(&self) -> usize {
218 self.duplicate.key().left
219 }
220
221 #[must_use]
223 pub const fn right_position(&self) -> usize {
224 self.duplicate.key().right
225 }
226
227 #[must_use]
229 pub const fn first_position(&self) -> usize {
230 self.duplicate.first_position()
231 }
232
233 #[must_use]
235 pub const fn repeated_positions(&self) -> &NonEmpty<usize, N> {
236 self.duplicate.repeated_positions()
237 }
238}
239
240impl<const N: usize> RepeatedRelationPairs<N> {
241 pub fn iter(&self) -> impl Iterator<Item = &RepeatedRelationPair<N>> {
243 self.pairs.iter()
244 }
245
246 #[must_use]
248 pub fn count(&self) -> usize {
249 self.pairs.count()
250 }
251}
252
253fn resolve_rows<'roster, Member, Key: Eq, Payload, const MEMBERS: usize, const ROWS: usize>(
254 roster: &'roster KeyedRoster<Member, Key, MEMBERS>,
255 payloads: &Bounded<Payload, ROWS>,
256 mut key_of: impl FnMut(&Payload) -> Key,
257) -> Result<Vec<ResolvedRosterMember<'roster, Member, Key>>, RowResolutionError<Key, ROWS>> {
258 let mut resolved = Vec::with_capacity(payloads.len());
259 let mut foreign = Vec::new();
260 for (offered_position, payload) in payloads.iter().enumerate() {
261 let key = key_of(payload);
262 match roster.indexed_get(&key) {
263 Some((position, retained, member)) => resolved.push(ResolvedRosterMember {
264 position,
265 key: retained,
266 member,
267 }),
268 None => foreign.push(ForeignRosterReference::at(key, offered_position)),
269 }
270 }
271 settle_resolved_rows(resolved, foreign)
272}
273
274fn settle_resolved_rows<Member, Key, const ROWS: usize>(
275 resolved: Vec<ResolvedRosterMember<'_, Member, Key>>,
276 foreign: Vec<ForeignRosterReference<Key>>,
277) -> Result<Vec<ResolvedRosterMember<'_, Member, Key>>, RowResolutionError<Key, ROWS>> {
278 match NonEmpty::new(foreign) {
279 Ok(foreign) => Err(RowResolutionError::Foreign(foreign)),
280 Err(NonEmptyError::Empty(_)) => Ok(resolved),
281 Err(NonEmptyError::Overflow(overflow)) => Err(RowResolutionError::Overflow(overflow)),
282 }
283}
284
285fn left_refusal<LeftKey, RightKey, const N: usize>(
286 refusal: RowResolutionError<LeftKey, N>,
287) -> KeyedRosterRowsError<LeftKey, RightKey, N> {
288 match refusal {
289 RowResolutionError::Overflow(overflow) => KeyedRosterRowsError::Overflow(overflow),
290 RowResolutionError::Foreign(foreign) => KeyedRosterRowsError::ForeignLeft(foreign),
291 }
292}
293
294fn right_refusal<LeftKey, RightKey, const N: usize>(
295 refusal: RowResolutionError<RightKey, N>,
296) -> KeyedRosterRowsError<LeftKey, RightKey, N> {
297 match refusal {
298 RowResolutionError::Overflow(overflow) => KeyedRosterRowsError::Overflow(overflow),
299 RowResolutionError::Foreign(foreign) => KeyedRosterRowsError::ForeignRight(foreign),
300 }
301}
302
303fn row_from_resolved<'rosters, Left, LeftKey, Right, RightKey, Payload>(
304 ((payload, left), right): (
305 (Payload, ResolvedRosterMember<'rosters, Left, LeftKey>),
306 ResolvedRosterMember<'rosters, Right, RightKey>,
307 ),
308) -> ReferencedRosterRow<'rosters, Left, LeftKey, Right, RightKey, Payload> {
309 ReferencedRosterRow {
310 left_position: left.position,
311 left_key: left.key,
312 left_member: left.member,
313 right_position: right.position,
314 right_key: right.key,
315 right_member: right.member,
316 payload,
317 }
318}
319
320fn canonical_indices<Left, LeftKey, Right, RightKey, Payload, const N: usize>(
321 rows: &Bounded<ReferencedRosterRow<'_, Left, LeftKey, Right, RightKey, Payload>, N>,
322) -> Result<Bounded<usize, N>, KeyedRosterRowsError<LeftKey, RightKey, N>> {
323 let mut canonical = rows
324 .iter()
325 .enumerate()
326 .map(|(authored, row)| CanonicalRelationPosition {
327 authored,
328 left: row.left_position,
329 right: row.right_position,
330 })
331 .collect::<Vec<_>>();
332 canonical.sort_by_key(|position| (position.left, position.right, position.authored));
333 Bounded::new(
334 canonical
335 .into_iter()
336 .map(|position| position.authored)
337 .collect(),
338 )
339 .map_err(KeyedRosterRowsError::Overflow)
340}
341
342fn repeated_relation_pairs<
343 Left,
344 LeftKey,
345 Right,
346 RightKey,
347 Payload,
348 const LEFT: usize,
349 const RIGHT: usize,
350 const ROWS: usize,
351>(
352 rows: &KeyedRosterRows<'_, Left, LeftKey, Right, RightKey, Payload, LEFT, RIGHT, ROWS>,
353) -> Option<RepeatedRelationPairs<ROWS>> {
354 let pairs = rows.rows.mapped(|row| RelationPair {
355 left: row.left_position,
356 right: row.right_position,
357 });
358 let pairs = NonEmpty::from_bounded(pairs).ok()?;
359 let duplicates = pairs.duplicate_keys()?;
360 Some(RepeatedRelationPairs {
361 pairs: duplicates.mapped(|duplicate| RepeatedRelationPair { duplicate }),
362 })
363}