1use std::ops::Mul;
2
3use num_traits::PrimInt;
4use rayon::prelude::*;
5use smol_str::SmolStr;
6
7pub type IndexTuple = Box<[IndexKey]>;
16
17#[derive(Clone, Debug)]
22pub enum Set {
23 Range(Vec<i64>),
24 Strings(Vec<SmolStr>),
25 Tuples(Vec<IndexTuple>),
26}
27
28impl Set {
29 pub fn range<T: PrimInt>(r: std::ops::Range<T>) -> Self {
38 let start = r.start.to_i64().expect("range start out of i64 range");
39 let end = r.end.to_i64().expect("range end out of i64 range");
40 Self::Range((start..end).collect())
41 }
42
43 pub fn from_ints<T, I>(iter: I) -> Self
49 where
50 T: PrimInt,
51 I: IntoIterator<Item = T>,
52 {
53 Self::Range(
54 iter.into_iter().map(|v| v.to_i64().expect("element out of i64 range")).collect(),
55 )
56 }
57
58 pub fn strings<I, S>(iter: I) -> Self
59 where
60 I: IntoIterator<Item = S>,
61 S: Into<SmolStr>,
62 {
63 Self::Strings(iter.into_iter().map(Into::into).collect())
64 }
65
66 pub fn tuples<I, T>(iter: I) -> Self
68 where
69 I: IntoIterator<Item = T>,
70 T: Into<IndexTuple>,
71 {
72 Self::Tuples(iter.into_iter().map(Into::into).collect())
73 }
74
75 pub fn product(a: &Set, b: &Set) -> Self {
81 let a_len = a.len();
82 let b_len = b.len();
83 let total = a_len.checked_mul(b_len).expect("Set::product size overflow");
84
85 const PAR_THRESHOLD: usize = 4096;
88 if total < PAR_THRESHOLD {
89 let mut out = Vec::with_capacity(total);
90 for ka in a {
91 for kb in b {
92 let mut parts: Vec<IndexKey> = Vec::new();
93 push_flat(&mut parts, ka.clone());
94 push_flat(&mut parts, kb);
95 out.push(parts.into_boxed_slice());
96 }
97 }
98 return Self::Tuples(out);
99 }
100
101 let a_keys: Vec<IndexKey> = a.iter().collect();
102 let b_keys: Vec<IndexKey> = b.iter().collect();
103 let out: Vec<IndexTuple> = (0..total)
104 .into_par_iter()
105 .map(|i| {
106 let mut parts: Vec<IndexKey> = Vec::new();
107 push_flat(&mut parts, a_keys[i / b_len].clone());
108 push_flat(&mut parts, b_keys[i % b_len].clone());
109 parts.into_boxed_slice()
110 })
111 .collect();
112 Self::Tuples(out)
113 }
114
115 pub fn filter<F>(&self, mut f: F) -> Self
118 where
119 F: FnMut(&IndexKey) -> bool,
120 {
121 match self {
122 Self::Range(v) => {
123 Self::Range(v.iter().copied().filter(|i| f(&IndexKey::Int(*i))).collect())
124 }
125 Self::Strings(v) => Self::Strings(
126 v.iter()
127 .filter_map(|s| {
128 let key = IndexKey::Str(s.clone());
129 f(&key).then(|| s.clone())
130 })
131 .collect(),
132 ),
133 Self::Tuples(v) => Self::Tuples(
134 v.iter()
135 .filter_map(|t| {
136 let key = IndexKey::Tuple(t.clone());
137 f(&key).then(|| match key {
138 IndexKey::Tuple(owned) => owned,
139 _ => unreachable!(),
140 })
141 })
142 .collect(),
143 ),
144 }
145 }
146
147 pub fn len(&self) -> usize {
148 match self {
149 Self::Range(v) => v.len(),
150 Self::Strings(v) => v.len(),
151 Self::Tuples(v) => v.len(),
152 }
153 }
154
155 pub fn is_empty(&self) -> bool {
156 self.len() == 0
157 }
158}
159
160fn push_flat(dst: &mut Vec<IndexKey>, k: IndexKey) {
161 match k {
162 IndexKey::Tuple(inner) => dst.extend(inner.into_vec()),
163 other => dst.push(other),
164 }
165}
166
167fn make_tuple<I: IntoIterator<Item = IndexKey>>(items: I) -> IndexTuple {
168 let mut v: Vec<IndexKey> = Vec::new();
169 for k in items {
170 push_flat(&mut v, k);
171 }
172 v.into_boxed_slice()
173}
174
175impl Mul<&Set> for &Set {
176 type Output = Set;
177 fn mul(self, rhs: &Set) -> Set {
178 Set::product(self, rhs)
179 }
180}
181
182#[derive(Clone, Debug, PartialEq, Eq, Hash)]
184pub enum IndexKey {
185 Int(i64),
186 Str(SmolStr),
187 Tuple(IndexTuple),
188}
189
190impl IndexKey {
191 pub fn tuple<I, T>(iter: I) -> Self
194 where
195 I: IntoIterator<Item = T>,
196 T: Into<IndexKey>,
197 {
198 Self::Tuple(make_tuple(iter.into_iter().map(Into::into)))
199 }
200
201 pub fn as_i64(&self) -> Option<i64> {
202 if let Self::Int(v) = self { Some(*v) } else { None }
203 }
204
205 pub fn as_str(&self) -> Option<&str> {
206 if let Self::Str(s) = self { Some(s.as_str()) } else { None }
207 }
208
209 pub fn as_tuple(&self) -> Option<&[IndexKey]> {
210 if let Self::Tuple(t) = self { Some(&t[..]) } else { None }
211 }
212}
213
214impl From<i64> for IndexKey {
215 fn from(v: i64) -> Self {
216 Self::Int(v)
217 }
218}
219
220impl From<i32> for IndexKey {
221 fn from(v: i32) -> Self {
222 Self::Int(i64::from(v))
223 }
224}
225
226impl From<usize> for IndexKey {
227 fn from(v: usize) -> Self {
228 Self::Int(i64::try_from(v).expect("usize -> i64 overflow"))
229 }
230}
231
232impl From<&str> for IndexKey {
233 fn from(s: &str) -> Self {
234 Self::Str(SmolStr::new(s))
235 }
236}
237
238impl From<String> for IndexKey {
239 fn from(s: String) -> Self {
240 Self::Str(SmolStr::from(s))
241 }
242}
243
244impl From<&String> for IndexKey {
245 fn from(s: &String) -> Self {
246 Self::Str(SmolStr::new(s.as_str()))
247 }
248}
249
250impl<A, B> From<(A, B)> for IndexKey
251where
252 A: Into<IndexKey>,
253 B: Into<IndexKey>,
254{
255 fn from(t: (A, B)) -> Self {
256 Self::Tuple(make_tuple([t.0.into(), t.1.into()]))
257 }
258}
259
260impl<A, B, C> From<(A, B, C)> for IndexKey
261where
262 A: Into<IndexKey>,
263 B: Into<IndexKey>,
264 C: Into<IndexKey>,
265{
266 fn from(t: (A, B, C)) -> Self {
267 Self::Tuple(make_tuple([t.0.into(), t.1.into(), t.2.into()]))
268 }
269}
270
271impl<A, B, C, D> From<(A, B, C, D)> for IndexKey
272where
273 A: Into<IndexKey>,
274 B: Into<IndexKey>,
275 C: Into<IndexKey>,
276 D: Into<IndexKey>,
277{
278 fn from(t: (A, B, C, D)) -> Self {
279 Self::Tuple(make_tuple([t.0.into(), t.1.into(), t.2.into(), t.3.into()]))
280 }
281}
282
283pub trait FromIndexKey: Sized {
297 fn from_index_key(k: &IndexKey) -> Self;
298}
299
300impl FromIndexKey for IndexKey {
301 fn from_index_key(k: &IndexKey) -> Self {
302 k.clone()
303 }
304}
305
306impl FromIndexKey for i64 {
307 fn from_index_key(k: &IndexKey) -> Self {
308 k.as_i64().unwrap_or_else(|| panic!("expected Int key, got {k:?}"))
309 }
310}
311
312impl FromIndexKey for i32 {
313 fn from_index_key(k: &IndexKey) -> Self {
314 let v = i64::from_index_key(k);
315 i32::try_from(v).unwrap_or_else(|_| panic!("key {v} out of i32 range"))
316 }
317}
318
319impl FromIndexKey for usize {
320 fn from_index_key(k: &IndexKey) -> Self {
321 let v = i64::from_index_key(k);
322 usize::try_from(v).unwrap_or_else(|_| panic!("key {v} out of usize range"))
323 }
324}
325
326impl FromIndexKey for String {
327 fn from_index_key(k: &IndexKey) -> Self {
328 k.as_str().unwrap_or_else(|| panic!("expected Str key, got {k:?}")).to_owned()
329 }
330}
331
332fn tuple_parts<'a>(k: &'a IndexKey, expected: usize) -> &'a [IndexKey] {
333 let p = k.as_tuple().unwrap_or_else(|| panic!("expected Tuple key, got {k:?}"));
334 assert_eq!(p.len(), expected, "expected tuple of arity {expected}, got arity {}", p.len());
335 p
336}
337
338impl<A, B> FromIndexKey for (A, B)
339where
340 A: FromIndexKey,
341 B: FromIndexKey,
342{
343 fn from_index_key(k: &IndexKey) -> Self {
344 let p = tuple_parts(k, 2);
345 (A::from_index_key(&p[0]), B::from_index_key(&p[1]))
346 }
347}
348
349impl<A, B, C> FromIndexKey for (A, B, C)
350where
351 A: FromIndexKey,
352 B: FromIndexKey,
353 C: FromIndexKey,
354{
355 fn from_index_key(k: &IndexKey) -> Self {
356 let p = tuple_parts(k, 3);
357 (A::from_index_key(&p[0]), B::from_index_key(&p[1]), C::from_index_key(&p[2]))
358 }
359}
360
361impl<A, B, C, D> FromIndexKey for (A, B, C, D)
362where
363 A: FromIndexKey,
364 B: FromIndexKey,
365 C: FromIndexKey,
366 D: FromIndexKey,
367{
368 fn from_index_key(k: &IndexKey) -> Self {
369 let p = tuple_parts(k, 4);
370 (
371 A::from_index_key(&p[0]),
372 B::from_index_key(&p[1]),
373 C::from_index_key(&p[2]),
374 D::from_index_key(&p[3]),
375 )
376 }
377}
378
379impl<'a> IntoIterator for &'a Set {
380 type Item = IndexKey;
381 type IntoIter = SetIter<'a>;
382 fn into_iter(self) -> Self::IntoIter {
383 self.iter()
384 }
385}
386
387impl Set {
388 pub fn iter(&self) -> SetIter<'_> {
389 SetIter { set: self, pos: 0 }
390 }
391
392 pub fn par_iter(&self) -> impl ParallelIterator<Item = IndexKey> + '_ {
393 match self {
394 Self::Range(v) => v.par_iter().map(|i| IndexKey::Int(*i)).collect::<Vec<_>>(),
395 Self::Strings(v) => v.par_iter().map(|s| IndexKey::Str(s.clone())).collect::<Vec<_>>(),
396 Self::Tuples(v) => v.par_iter().map(|t| IndexKey::Tuple(t.clone())).collect::<Vec<_>>(),
397 }
398 .into_par_iter()
399 }
400}
401
402#[derive(Debug)]
403pub struct SetIter<'a> {
404 set: &'a Set,
405 pos: usize,
406}
407
408impl<'a> Iterator for SetIter<'a> {
409 type Item = IndexKey;
410 fn next(&mut self) -> Option<Self::Item> {
411 let out = match self.set {
412 Set::Range(v) => v.get(self.pos).copied().map(IndexKey::Int),
413 Set::Strings(v) => v.get(self.pos).cloned().map(IndexKey::Str),
414 Set::Tuples(v) => v.get(self.pos).cloned().map(IndexKey::Tuple),
415 };
416 if out.is_some() {
417 self.pos += 1;
418 }
419 out
420 }
421}