#![no_std]
#![feature(core_intrinsics, step_trait)]
use core::intrinsics::{likely, unlikely};
use core::iter::Step;
use core::ops::{
Bound::{Excluded, Included, Unbounded},
RangeBounds,
};
use crate::utils::max_value;
mod utils;
pub struct IncBy<T: Copy + Default + Step, const STEP: usize> {
start: T,
end: T,
had_overflow: bool,
was_unbound: bool,
}
pub struct DecBy<T: Copy + Default + Step, const STEP: usize> {
start: T,
end: T,
had_overflow: bool,
}
impl<T: Copy + Default + Step, const STEP: usize> IncBy<T, STEP> {
#[inline(always)]
fn new<R: RangeBounds<T>>(bounds: R) -> IncBy<T, STEP> {
let start = match bounds.start_bound() {
Included(&idx) => idx,
Excluded(&idx) => idx,
Unbounded => Default::default(),
};
let mut had_overflow = false;
let mut was_unbound = false;
let end = match bounds.end_bound() {
Included(&idx) => {
if let Some(res) = Step::forward_checked(idx, STEP) {
res
} else {
had_overflow = true;
idx
}
}
Excluded(&idx) => {
if let Some(res) = Step::forward_checked(idx, STEP - 1) {
res
} else {
had_overflow = true;
idx
}
}
Unbounded => {
was_unbound = true;
Step::forward(Default::default(), max_value(&start))
}
};
IncBy {
start,
end,
had_overflow,
was_unbound,
}
}
}
impl<T: Copy + Default + Step, const STEP: usize> DecBy<T, STEP> {
#[inline(always)]
fn new<R: RangeBounds<T>>(bounds: R) -> DecBy<T, STEP> {
let start = match bounds.end_bound() {
Included(&idx) => idx,
Excluded(&idx) => Step::forward_checked(idx, 1).unwrap_or(idx),
Unbounded => Step::forward(Default::default(), 1),
};
let mut had_overflow = false;
let end = match bounds.start_bound() {
Included(&idx) => {
if let Some(res) = Step::forward_checked(idx, STEP) {
res
} else {
had_overflow = true;
idx
}
}
Excluded(&idx) => {
if let Some(res) = Step::forward_checked(idx, STEP + 1) {
res
} else {
had_overflow = true;
idx
}
}
Unbounded => Default::default(),
};
DecBy {
start,
end,
had_overflow,
}
}
}
impl<T: Copy + Default + Step, const STEP: usize> Iterator for IncBy<T, STEP> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
if unlikely(self.had_overflow) {
self.had_overflow = false;
let res = Some(self.start);
self.start = Step::forward_checked(self.start, STEP).unwrap_or(self.start);
res
} else if let Some(end_back) = Step::backward_checked(self.end, STEP) {
if likely(self.start <= end_back) {
let res = Some(self.start);
self.start = Step::forward(self.start, STEP);
res
} else if unlikely(self.was_unbound) {
self.was_unbound = false;
Some(self.start)
} else {
None
}
} else {
None
}
}
}
impl<T: Copy + Default + Step, const STEP: usize> Iterator for DecBy<T, STEP> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
if unlikely(self.had_overflow) {
self.had_overflow = false;
Some(self.end)
} else if let Some(start_forward) = Step::forward_checked(self.start, STEP) {
if likely(start_forward <= self.end) {
self.end = Step::backward(self.end, STEP);
Some(self.end)
} else {
None
}
} else {
None
}
}
}
pub trait IntoIncBy<T: Copy + Default + Step>: RangeBounds<T> {
fn inc_by<const STEP: usize>(self) -> IncBy<T, STEP>;
}
pub trait IntoDecBy<T: Copy + Default + Step>: RangeBounds<T> {
fn dec_by<const STEP: usize>(self) -> DecBy<T, STEP>;
}
impl<T: Copy + Default + Step, R: RangeBounds<T>> IntoIncBy<T> for R {
#[inline(always)]
fn inc_by<const STEP: usize>(self) -> IncBy<T, STEP> {
IncBy::<T, STEP>::new(self)
}
}
impl<T: Copy + Default + Step, R: RangeBounds<T>> IntoDecBy<T> for R {
#[inline(always)]
fn dec_by<const STEP: usize>(self) -> DecBy<T, STEP> {
DecBy::<T, STEP>::new(self)
}
}