#[derive(Copy,Clone)]
pub enum Strategy {
Clamp,
Rotate,
RotateWithInvalidState,
RotateFromInvalidState,
}
#[derive(Copy, Clone, PartialEq)]
pub(crate) struct VectorIndex {
value: usize,
}
impl VectorIndex {
const INVALID_INDEX: usize = usize::MAX;
#[allow(non_upper_case_globals)]
pub(crate) const Invalid: VectorIndex = VectorIndex { value: usize::MAX };
#[allow(non_upper_case_globals)]
pub(crate) const First: VectorIndex = VectorIndex { value: 0 };
#[inline(always)]
pub fn last(count: usize) -> Self {
Self {
value: if count > 0 {
count - 1
} else {
Self::INVALID_INDEX
},
}
}
#[inline(always)]
pub fn with_value(value: usize) -> Self {
Self { value }
}
#[inline(always)]
pub fn index(&self) -> usize {
self.value
}
#[inline(always)]
pub fn is_valid(&self) -> bool {
self.value != Self::INVALID_INDEX
}
#[inline(always)]
pub fn in_range(&self, count: usize) -> bool {
self.value < count
}
#[inline(always)]
pub fn set(&mut self, value: usize, count: usize, clamp: bool) {
if count == 0 {
self.value = Self::INVALID_INDEX;
return;
}
if clamp {
self.value = value.min(count - 1);
} else {
self.value = if value >= count {
Self::INVALID_INDEX
} else {
value
};
}
}
#[inline(always)]
pub fn add(&mut self, value: usize, count: usize, strategy: Strategy) {
if count == 0 {
self.value = Self::INVALID_INDEX;
return;
}
match strategy {
Strategy::Clamp => {
if self.value != Self::INVALID_INDEX {
self.value += value;
if self.value >= count {
self.value = count - 1;
}
}
}
Strategy::Rotate => {
if self.value != Self::INVALID_INDEX {
self.value = (self.value + value) % count;
}
}
Strategy::RotateWithInvalidState => {
if self.value != Self::INVALID_INDEX {
self.value += value;
if self.value >= count {
self.value = Self::INVALID_INDEX
}
} else {
self.value = 0; }
}
Strategy::RotateFromInvalidState => {
if self.value != Self::INVALID_INDEX {
self.value = (self.value + value) % count;
} else {
self.value = 0; }
}
}
}
#[inline(always)]
pub fn sub(&mut self, value: usize, count: usize, strategy: Strategy) {
if count == 0 {
self.value = Self::INVALID_INDEX;
return;
}
match strategy {
Strategy::Clamp => {
if self.value != Self::INVALID_INDEX {
if self.value >= value {
self.value -= value;
} else {
self.value = 0;
}
}
}
Strategy::Rotate => {
if self.value != Self::INVALID_INDEX {
let value = value % count;
self.value = (self.value + count - value) % count;
}
}
Strategy::RotateWithInvalidState => {
if self.value != Self::INVALID_INDEX {
if self.value >= value {
self.value -= value;
} else {
self.value = Self::INVALID_INDEX;
}
} else {
self.value = count - 1;
}
}
Strategy::RotateFromInvalidState => {
if self.value != Self::INVALID_INDEX {
let value = value % count;
self.value = (self.value + count - value) % count;
} else {
self.value = count - 1;
}
}
}
}
}
impl Default for VectorIndex {
fn default() -> Self {
Self {
value: Self::INVALID_INDEX,
}
}
}
impl From<usize> for VectorIndex {
fn from(value: usize) -> Self {
VectorIndex { value }
}
}
impl From<u32> for VectorIndex {
fn from(value: u32) -> Self {
VectorIndex {
value: value as usize,
}
}
}