#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::intervals::absolute::{AbsBound, HasAbsBoundPair};
use crate::intervals::relative::{HasRelBoundPair, RelBound};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum BoundPosition {
Start(usize),
End(usize),
}
impl BoundPosition {
pub const MAX: Self = BoundPosition::End(usize::MAX);
pub const MIN: Self = BoundPosition::Start(usize::MIN);
#[must_use]
pub fn index(&self) -> usize {
match self {
Self::Start(i) | Self::End(i) => *i,
}
}
#[must_use]
pub fn get_abs_bound<'j, I, J>(&self, abs_bounds: I) -> Option<AbsBound>
where
I: IntoIterator<Item = &'j J>,
J: 'j + HasAbsBoundPair,
{
match self {
Self::Start(i) => abs_bounds
.into_iter()
.nth(*i)
.map(|bounds| bounds.abs_start().to_bound()),
Self::End(i) => abs_bounds.into_iter().nth(*i).map(|bounds| bounds.abs_end().to_bound()),
}
}
#[must_use]
pub fn get_rel_bound<'j, I, J>(&self, rel_bounds: I) -> Option<RelBound>
where
I: IntoIterator<Item = &'j J>,
J: 'j + HasRelBoundPair,
{
match self {
Self::Start(i) => rel_bounds
.into_iter()
.nth(*i)
.map(|bounds| bounds.rel_start().to_bound()),
Self::End(i) => rel_bounds.into_iter().nth(*i).map(|bounds| bounds.rel_end().to_bound()),
}
}
pub fn add_interval_index(&mut self, count: usize) -> bool {
match self {
Self::Start(i) | Self::End(i) => {
if let Some(new_i) = i.checked_add(count) {
*i = new_i;
false
} else {
*self = Self::MAX;
true
}
},
}
}
pub fn sub_interval_index(&mut self, count: usize) -> bool {
match self {
Self::Start(i) | Self::End(i) => {
if let Some(new_i) = i.checked_sub(count) {
*i = new_i;
false
} else {
*self = Self::MIN;
true
}
},
}
}
pub fn increment_interval_index(&mut self) -> bool {
self.add_interval_index(1)
}
pub fn decrement_interval_index(&mut self) -> bool {
self.sub_interval_index(1)
}
pub fn advance_by(&mut self, count: usize) -> bool {
if count.is_multiple_of(2) {
match self {
Self::Start(i) => {
if let Some(new_i) = i.checked_add(count.saturating_div(2)) {
*self = Self::Start(new_i);
false
} else {
*self = Self::MAX;
true
}
},
Self::End(i) => {
if let Some(new_i) = i.checked_add(count.saturating_div(2)) {
*self = Self::End(new_i);
false
} else {
*self = Self::MAX;
true
}
},
}
} else {
match self {
Self::Start(i) => {
if let Some(new_i) = i.checked_add(count.saturating_div(2)) {
*self = Self::End(new_i);
false
} else {
*self = Self::MAX;
true
}
},
Self::End(i) => {
if let Some(new_i) = i.checked_add(count.saturating_div(2).saturating_add(1)) {
*self = Self::Start(new_i);
false
} else {
*self = Self::MAX;
true
}
},
}
}
}
pub fn advance_back_by(&mut self, count: usize) -> bool {
if count.is_multiple_of(2) {
match self {
Self::Start(i) => {
if let Some(new_i) = i.checked_sub(count.saturating_div(2)) {
*self = Self::Start(new_i);
false
} else {
*self = Self::MIN;
true
}
},
Self::End(i) => {
if let Some(new_i) = i.checked_sub(count.saturating_div(2)) {
*self = Self::End(new_i);
false
} else {
*self = Self::MIN;
true
}
},
}
} else {
match self {
Self::Start(i) => {
if let Some(new_i) = i.checked_sub(count.saturating_div(2).saturating_add(1)) {
*self = Self::End(new_i);
false
} else {
*self = Self::MIN;
true
}
},
Self::End(i) => {
if let Some(new_i) = i.checked_sub(count.saturating_div(2)) {
*self = Self::Start(new_i);
false
} else {
*self = Self::MIN;
true
}
},
}
}
}
pub fn next_bound(&mut self) -> bool {
self.advance_by(1)
}
pub fn prev_bound(&mut self) -> bool {
self.advance_back_by(1)
}
}
impl Default for BoundPosition {
fn default() -> Self {
BoundPosition::MIN
}
}