onion/
lib.rs

1#![no_std]
2extern crate alloc;
3use alloc::vec;
4use alloc::vec::Vec;
5
6pub fn union<A: Eq>(mut b: impl Iterator<Item: Iterator<Item = A>>) -> Union<A> {
7    let Some(a) = b.next() else {
8        return Union {
9            vals: vec![],
10            poss: vec![],
11        };
12    };
13    let mut vals = a.collect::<Vec<_>>();
14    let pos1s = vals.iter().enumerate().map(|a| a.0).collect();
15    let mut poss = vec![pos1s];
16    for b in b {
17        let mut pos2s: Vec<usize> = vec![];
18        for b in b {
19            match vals
20                .iter()
21                .enumerate()
22                .filter(|(i, a)| !pos2s.contains(&i))
23                .find(|(i, x)| **x == b)
24            {
25                Some(c) => pos2s.push(c.0),
26                None => {
27                    pos2s.push(vals.len());
28                    vals.push(b)
29                }
30            }
31        }
32        poss.push(pos2s);
33    }
34    Union { vals, poss }
35}
36pub struct Union<A> {
37    pub vals: Vec<A>,
38    pub poss: Vec<Vec<usize>>,
39}
40impl<A> Union<A> {
41    pub fn create<B, E>(
42        &self,
43        i: usize,
44        default: impl FnMut(&A) -> Result<B, E>,
45        vals: impl Iterator<Item = Result<B, E>>,
46    ) -> Result<Vec<B>, E> {
47        let mut bs: Vec<B> = self.vals.iter().map(default).collect::<Result<_, E>>()?;
48        for (j, b) in self.poss[i].iter().cloned().zip(vals) {
49            bs[j] = b?;
50        }
51        return Ok(bs);
52    }
53}