wolfpack 0.3.1

A package manager and a build tool that supports major package formats (deb, RPM, ipk, pkg, MSIX).
Documentation
use std::ops::RangeInclusive;

use arbitrary::Unstructured;
use gcollections::ops::*;
use interval::ops::*;
use interval::Interval;
use interval::IntervalSet;
use rand::Rng;

#[derive(Debug, Clone)]
pub struct Chars {
    intervals: IntervalSet<u32>,
}

impl Chars {
    pub fn union<O: Into<Self>>(&self, other: O) -> Self {
        let other: Self = other.into();
        Self {
            intervals: self.intervals.union(&other.intervals),
        }
    }

    pub fn difference<O: Into<Self>>(&self, other: O) -> Self {
        let other: Self = other.into();
        Self {
            intervals: self.intervals.difference(&other.intervals),
        }
    }

    pub fn get(&self, mut i: u32) -> Option<char> {
        for interval in self.intervals.iter() {
            let s = interval.size();
            if i < s {
                return Some(
                    char::from_u32(interval.lower() + i)
                        .unwrap_or_else(|| panic!("failed on {:x}", interval.lower() + i)),
                );
            }
            i -= s;
        }
        None
    }

    pub fn is_empty(&self) -> bool {
        self.intervals.is_empty()
    }

    pub fn len(&self) -> u32 {
        self.intervals.size()
    }

    pub fn contains(&self, ch: char) -> bool {
        let ch = ch as u32;
        self.intervals.contains(&ch)
    }

    pub fn arbitrary_char(&self, u: &mut Unstructured<'_>) -> arbitrary::Result<char> {
        let i = u.int_in_range(0..=(self.len() - 1))?;
        Ok(self.get(i).expect("should not fail"))
    }

    pub fn arbitrary_string(
        &self,
        u: &mut Unstructured<'_>,
        len: usize,
    ) -> arbitrary::Result<String> {
        let mut s = String::with_capacity(len);
        for _ in 0..len {
            s.push(self.arbitrary_char(u)?);
        }
        Ok(s)
    }

    pub fn arbitrary_byte_string(
        &self,
        u: &mut Unstructured<'_>,
        len: usize,
    ) -> arbitrary::Result<String> {
        let mut s = String::with_capacity(len);
        for _ in 0..len {
            s.push(self.arbitrary_char(u)?);
            if s.len() > len {
                s.pop();
                break;
            }
        }
        Ok(s)
    }

    pub fn random_char<R: Rng>(&self, rng: &mut R) -> char {
        let i = rng.gen_range(0..=(self.len() - 1));
        self.get(i).expect("should not fail")
    }

    pub fn random_string<R: Rng>(&self, rng: &mut R, len: usize) -> String {
        let mut s = String::with_capacity(len);
        for _ in 0..len {
            s.push(self.random_char(rng));
        }
        s
    }
}

impl From<RangeInclusive<char>> for Chars {
    fn from(other: RangeInclusive<char>) -> Self {
        let (a, b) = other.into_inner();
        let mut intervals = IntervalSet::empty();
        intervals.extend([Interval::new(a as u32, b as u32)]);
        Self { intervals }
    }
}

impl<const N: usize> From<[RangeInclusive<char>; N]> for Chars {
    fn from(other: [RangeInclusive<char>; N]) -> Self {
        let mut iter = other.into_iter();
        let mut set = Self::from(iter.next().unwrap());
        for range in iter {
            set = set.union(range);
        }
        set
    }
}

impl From<&[char]> for Chars {
    fn from(other: &[char]) -> Self {
        let mut intervals = IntervalSet::empty();
        for ch in other {
            intervals.extend([Interval::new(*ch as u32, *ch as u32)]);
        }
        Self { intervals }
    }
}

impl<const N: usize> From<[char; N]> for Chars {
    fn from(other: [char; N]) -> Self {
        Self::from(&other[..])
    }
}