use std::collections::BTreeSet;
use std::fmt;
pub struct SeqSet {
set: BTreeSet<u32>,
}
impl SeqSet {
pub fn new() -> Self {
SeqSet {
set: BTreeSet::new(),
}
}
}
impl std::ops::Deref for SeqSet {
type Target = BTreeSet<u32>;
fn deref(&self) -> &Self::Target {
&self.set
}
}
impl std::ops::DerefMut for SeqSet {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.set
}
}
impl<const N: usize> std::convert::From<[u32; N]> for SeqSet {
fn from(arr: [u32; N]) -> Self {
SeqSet {
set: BTreeSet::from(arr),
}
}
}
impl std::convert::From<&BTreeSet<u32>> for SeqSet {
fn from(set: &BTreeSet<u32>) -> Self {
SeqSet { set: set.clone() }
}
}
impl FromIterator<u32> for SeqSet {
fn from_iter<T: IntoIterator<Item = u32>>(iter: T) -> Self {
let mut set = BTreeSet::new();
for i in iter {
set.insert(i);
}
SeqSet { set }
}
}
impl fmt::Display for SeqSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut is_range = false;
let mut last: u32 = 0;
for id in &self.set {
if last == 0 {
write!(f, "{}", id)?;
} else if *id == u32::MAX {
write!(f, ":*")?;
} else if *id == (last + 1) {
is_range = true;
} else {
if is_range {
write!(f, ":{},{}", last, *id)?;
} else {
write!(f, ",{}", *id)?;
}
is_range = false;
}
last = *id;
}
if is_range {
write!(f, ":{}", last)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_seq_set() {
let set = SeqSet::from([1]);
assert_eq!(set.to_string(), String::from("1"));
let set = SeqSet::from([1, 2]);
assert_eq!(set.to_string(), String::from("1:2"));
let set = SeqSet::from([1, 3]);
assert_eq!(set.to_string(), String::from("1,3"));
let set = SeqSet::from([1, 3, 4, 5, 19]);
assert_eq!(set.to_string(), String::from("1,3:5,19"));
let set = SeqSet::from([1, 2, 3, 4, 6, 8, 10, 11, 12]);
assert_eq!(set.to_string(), String::from("1:4,6,8,10:12"));
let set = SeqSet::from([1, 3, 2, 10, 6, 8, 10, 4, 11, 12]);
assert_eq!(set.to_string(), String::from("1:4,6,8,10:12"));
let set = SeqSet::from([1, u32::MAX]);
assert_eq!(set.to_string(), String::from("1:*"));
}
}