use super::Ixs;
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Slice {
pub start: Ixs,
pub end: Option<Ixs>,
pub step: Ixs,
}
impl Slice {
pub fn new(start: Ixs, end: Option<Ixs>, step: Ixs) -> Self {
debug_assert_ne!(step, 0, "step must be non-zero");
Self { start, end, step }
}
pub fn start(&self) -> Ixs {
self.start
}
pub fn end(&self) -> Option<Ixs> {
self.end
}
pub fn step(&self) -> Ixs {
self.step
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(rename_all = "snake_case")
)]
pub enum SliceType {
Index(Ixs),
Slice(Slice),
NewAxis,
}
impl SliceType {
pub fn new_axis() -> Self {
Self::NewAxis
}
pub fn index(index: Ixs) -> Self {
Self::Index(index)
}
pub fn slice(start: Ixs, end: Option<Ixs>, step: Ixs) -> Self {
Self::Slice(Slice::new(start, end, step))
}
}
pub struct Slices {
slices: Vec<SliceType>,
}
impl Slices {
pub fn new(slices: impl IntoIterator<Item = SliceType>) -> Self {
Self {
slices: Vec::from_iter(slices),
}
}
pub fn iter(&self) -> core::slice::Iter<'_, SliceType> {
self.slices.iter()
}
}
macro_rules! impl_from_range {
($self:ty, $constructor:expr, $idx:ty, [$($index:ty),*]) => {
$(
impl_from_range!($self, $constructor, $idx, $index);
)*
};
($self:ty, $constructor:expr, $idx:ty, $index:ty) => {
impl From<core::ops::Range<$index>> for $self {
#[inline]
fn from(r: core::ops::Range<$index>) -> $self {
$constructor(r.start as $idx, Some(r.end as $idx), 1)
}
}
impl From<core::ops::RangeFrom<$index>> for $self {
#[inline]
fn from(r: core::ops::RangeFrom<$index>) -> $self {
$constructor(r.start as $idx, None, 1)
}
}
impl From<core::ops::RangeInclusive<$index>> for $self {
#[inline]
fn from(r: core::ops::RangeInclusive<$index>) -> $self {
let end = *r.end() as $idx;
$constructor(*r.start() as $idx, if end == -1 { None } else { Some(end + 1) }, 1)
}
}
impl From<core::ops::RangeTo<$index>> for $self {
#[inline]
fn from(r: core::ops::RangeTo<$index>) -> $self {
$constructor(0, Some(r.end as $idx), 1)
}
}
impl From<core::ops::RangeToInclusive<$index>> for $self {
#[inline]
fn from(r: core::ops::RangeToInclusive<$index>) -> $self {
let end = r.end as $idx;
$constructor(0, if end == -1 { None } else { Some(end + 1) }, 1)
}
}
};
}
impl_from_range!(Slice, Slice::new, Ixs, [i32, isize, usize]);
impl_from_range!(SliceType, SliceType::slice, Ixs, [i32, isize, usize]);