use super::{
handle::{Handle, Index},
Arena,
};
use std::{fmt, marker::PhantomData, ops};
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
#[cfg_attr(
any(feature = "serialize", feature = "deserialize"),
serde(transparent)
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(test, derive(PartialEq))]
pub struct Range<T> {
pub(super) inner: ops::Range<u32>,
#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
marker: PhantomData<T>,
}
impl<T> Range<T> {
pub(crate) const fn erase_type(self) -> Range<()> {
let Self { inner, marker: _ } = self;
Range {
inner,
marker: PhantomData,
}
}
}
#[derive(Clone, Debug, thiserror::Error)]
#[cfg_attr(test, derive(PartialEq))]
#[error("Handle range {range:?} of {kind} is either not present, or inaccessible yet")]
pub struct BadRangeError {
kind: &'static str,
range: Range<()>,
}
impl BadRangeError {
pub fn new<T>(range: Range<T>) -> Self {
Self {
kind: std::any::type_name::<T>(),
range: range.erase_type(),
}
}
}
impl<T> Clone for Range<T> {
fn clone(&self) -> Self {
Range {
inner: self.inner.clone(),
marker: self.marker,
}
}
}
impl<T> fmt::Debug for Range<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "[{}..{}]", self.inner.start, self.inner.end)
}
}
impl<T> Iterator for Range<T> {
type Item = Handle<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.inner.start < self.inner.end {
let next = self.inner.start;
self.inner.start += 1;
Some(Handle::new(Index::new(next).unwrap()))
} else {
None
}
}
}
impl<T> Range<T> {
pub fn new_from_bounds(first: Handle<T>, last: Handle<T>) -> Self {
Self {
inner: (first.index() as u32)..(last.index() as u32 + 1),
marker: Default::default(),
}
}
pub(super) fn full_range_from_size(size: usize) -> Self {
Self {
inner: 0..size as u32,
marker: Default::default(),
}
}
pub fn first_and_last(&self) -> Option<(Handle<T>, Handle<T>)> {
if self.inner.start < self.inner.end {
Some((
Handle::new(Index::new(self.inner.start).unwrap()),
Handle::new(Index::new(self.inner.end - 1).unwrap()),
))
} else {
None
}
}
pub fn index_range(&self) -> ops::Range<u32> {
self.inner.clone()
}
pub fn from_index_range(inner: ops::Range<u32>, arena: &Arena<T>) -> Self {
assert!(inner.start <= inner.end);
assert!(inner.end as usize <= arena.len());
Self {
inner,
marker: Default::default(),
}
}
}