partial-enum 0.0.4

proc-macro generating partially inhabited enums
Documentation
pub struct Permutations {
    current: u64,
    upper_bound: u64,
}

pub struct Permutation {
    flags: u64,
    upper_bound: u64,
}

impl Permutations {
    pub fn new(set_size: usize) -> Self {
        assert!(set_size < 64);
        Permutations {
            current: 0,
            upper_bound: 1 << set_size,
        }
    }
}

impl Iterator for Permutations {
    type Item = Permutation;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current == self.upper_bound {
            return None;
        }
        let current = self.current;
        self.current += 1;
        Some(Permutation {
            flags: current,
            upper_bound: self.upper_bound,
        })
    }
}

impl Iterator for Permutation {
    type Item = bool;

    fn next(&mut self) -> Option<Self::Item> {
        if self.upper_bound > 1 {
            self.upper_bound >>= 1;
            Some(match self.flags & self.upper_bound {
                0 => false,
                _ => true,
            })
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashSet;

    #[test]
    fn test_permutations() {
        let mut expected = HashSet::new();
        expected.insert(vec![false, false, false]);
        expected.insert(vec![false, false, true]);
        expected.insert(vec![false, true, false]);
        expected.insert(vec![false, true, true]);
        expected.insert(vec![true, false, false]);
        expected.insert(vec![true, false, true]);
        expected.insert(vec![true, true, false]);
        expected.insert(vec![true, true, true]);

        let permutations = Permutations::new(3);
        let got: HashSet<Vec<bool>> = permutations.map(|perm| perm.collect()).collect();

        assert_eq!(got, expected);
    }
}