diff --git a/common/rust/src/lib.rs b/common/rust/src/lib.rs index b083d9b..457791d 100644 --- a/common/rust/src/lib.rs +++ b/common/rust/src/lib.rs @@ -2,4 +2,62 @@ mod section_range; +use std::mem; + pub use section_range::{EmptyRange, InvalidSectionString, SectionRange}; + +pub enum UpToTwo { + Zero, + One(T), + Two(T, T), +} + +impl UpToTwo { + pub fn is_empty(&self) -> bool { + matches!(self, UpToTwo::Zero) + } + + pub fn first(&self) -> Option<&T> { + match self { + UpToTwo::Zero => None, + UpToTwo::One(x) | UpToTwo::Two(x, _) => Some(x), + } + } + + pub fn second(&self) -> Option<&T> { + match self { + UpToTwo::Zero | UpToTwo::One(_) => None, + UpToTwo::Two(_, x) => Some(x), + } + } +} + +impl IntoIterator for UpToTwo { + type Item = T; + + type IntoIter = UpToTwoIter; + + fn into_iter(self) -> Self::IntoIter { + UpToTwoIter(self) + } +} + +pub struct UpToTwoIter(UpToTwo); + +impl Iterator for UpToTwoIter { + type Item = T; + + fn next(&mut self) -> Option { + let mut content = UpToTwo::Zero; + mem::swap(&mut self.0, &mut content); + + let (ret, mut content) = match content { + UpToTwo::Zero => (None, UpToTwo::Zero), + UpToTwo::One(x) => (Some(x), UpToTwo::Zero), + UpToTwo::Two(x, y) => (Some(x), UpToTwo::One(y)), + }; + mem::swap(&mut self.0, &mut content); + + ret + } +}