#[cfg(feature = "alloc")]
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{
array::IntoIter as ArrayIter,
cmp::Ordering,
fmt::{Debug, Display, Formatter, Result as FmtResult},
hash::{Hash, Hasher},
iter::Flatten,
ops,
};
#[macro_export]
macro_rules! re_arr {
() => (
$crate::ReArr::new()
);
($elem:expr; $n:expr) => (
$crate::ReArr::from_arr([Some($elem); $n])
);
($($x:expr),+ $(,)?) => (
$crate::ReArr::from_arr([$(Some($x)),+])
);
($($x:expr),+; $($rest:expr),* $(,)?) => (
$crate::ReArr::from_arr_and_len(&[$(Some($x)),+, $($rest),*])
);
}
pub struct ReArr<T, const N: usize> {
pub(crate) arr: [Option<T>; N],
arr_len: usize,
}
impl<T: Clone, const N: usize> Clone for ReArr<T, N> {
#[inline]
fn clone(&self) -> Self {
Self {
arr: self.arr.clone(),
arr_len: self.arr_len,
}
}
}
impl<T: PartialOrd, const N: usize> PartialOrd for ReArr<T, N> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T: Ord, const N: usize> Ord for ReArr<T, N> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
impl<T: PartialEq, const N: usize> PartialEq for ReArr<T, N> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<T: PartialEq + Eq, const N: usize> Eq for ReArr<T, N> {}
impl<T: Hash, const N: usize> Hash for ReArr<T, N> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.iter().for_each(|x| x.hash(state));
}
}
impl<T, const N: usize> Default for ReArr<T, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T: Copy, const N: usize> ReArr<T, N> {
#[must_use]
#[inline]
pub const fn from_arr_and_len(arr: &[Option<T>; N]) -> Self {
let mut arr_len = 0;
while arr_len < N {
if arr[arr_len].is_none() {
break;
}
arr_len += 1;
}
Self { arr: *arr, arr_len }
}
}
impl<T, const N: usize> ReArr<T, N> {
const DEFAULT_ARR_VALUE: Option<T> = None;
#[must_use]
#[inline]
pub const fn new() -> Self {
Self {
arr: [Self::DEFAULT_ARR_VALUE; N],
arr_len: 0,
}
}
#[must_use]
#[inline]
pub const fn from_arr(arr: [Option<T>; N]) -> Self {
Self { arr, arr_len: N }
}
#[inline]
pub fn push(&mut self, val: T) {
self.arr[self.arr_len] = Some(val);
self.arr_len += 1;
}
#[inline]
pub const fn pop(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
self.arr_len -= 1;
self.arr[self.arr_len].take()
}
}
#[must_use]
#[inline]
pub fn get(&self, idx: usize) -> Option<&T> {
self.arr.get(idx).and_then(|item| item.as_ref())
}
#[must_use]
#[inline]
pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
self.arr.get_mut(idx).and_then(|item| item.as_mut())
}
#[inline]
pub const fn len(&self) -> usize {
self.arr_len
}
#[inline]
pub const fn capacity(&self) -> usize {
N
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.arr[len..].iter_mut().for_each(|x| *x = None);
self.arr_len = self.arr_len.min(len);
}
#[inline]
pub fn clear(&mut self) {
self.arr.iter_mut().for_each(|x| *x = None);
self.arr_len = 0;
}
#[inline]
pub const fn first(&self) -> Option<&T> {
if N == 0 {
None
} else {
self.arr[0].as_ref()
}
}
#[inline]
pub const fn first_mut(&mut self) -> Option<&mut T> {
if N == 0 {
None
} else {
self.arr[0].as_mut()
}
}
#[inline]
pub const fn last(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
self.arr[self.arr_len - 1].as_ref()
}
}
#[inline]
pub const fn last_mut(&mut self) -> Option<&mut T> {
if self.is_empty() {
None
} else {
self.arr[self.arr_len - 1].as_mut()
}
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.arr_len == 0
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
self.arr.iter().flatten()
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> + '_ {
self.arr.iter_mut().flatten()
}
#[inline]
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
iter.into_iter().for_each(|x| self.push(x));
}
#[cfg(feature = "alloc")]
#[inline]
pub fn into_vec(self) -> Vec<T> {
self.into_iter().collect()
}
#[cfg(feature = "alloc")]
#[inline]
pub fn ref_vec(&self) -> Vec<&T> {
self.iter().collect()
}
}
impl<T: Clone, const N: usize> ReArr<T, N> {
#[cfg(feature = "alloc")]
#[inline]
pub fn to_vec(&self) -> Vec<T> {
self.iter().cloned().collect()
}
pub fn resize(&mut self, new_len: usize, val: T) {
assert!(new_len <= N, "new length cannot be greater than the internal array length");
if new_len > self.arr_len {
self.arr[self.arr_len..new_len].fill(Some(val));
} else {
self.arr[new_len..].fill(None);
}
self.arr_len = new_len;
}
pub fn resize_with<F: FnMut() -> T>(&mut self, new_len: usize, mut f: F) {
assert!(new_len <= N, "new length cannot be greater than the internal array length");
if new_len > self.arr_len {
self.arr[self.arr_len..new_len].fill(Some(f()));
} else {
self.arr[new_len..].fill(None);
}
self.arr_len = new_len;
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
let val = self.arr[index].take().unwrap();
for i in index..self.arr_len - 1 {
self.arr[i] = self.arr[i + 1].take();
}
self.arr_len -= 1;
val
}
#[inline]
pub const fn swap_remove(&mut self, index: usize) -> T {
let last_value = self.pop().unwrap();
self.arr[index].replace(last_value).unwrap()
}
}
#[cfg(feature = "alloc")]
impl<T: ToString, const N: usize> ReArr<T, N> {
pub fn join(&self, sep: &str) -> String {
self.iter()
.enumerate()
.fold(String::with_capacity(self.arr_len), |mut s, (i, item)| {
if i != 0 {
s.push_str(sep);
}
s.push_str(&item.to_string());
s
})
}
}
impl<T, const N: usize> ops::Index<usize> for ReArr<T, N> {
type Output = T;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
self.arr[idx].as_ref().unwrap()
}
}
impl<T, const N: usize> ops::IndexMut<usize> for ReArr<T, N> {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
self.arr[idx].as_mut().unwrap()
}
}
impl<T, const N: usize> IntoIterator for ReArr<T, N> {
type Item = T;
type IntoIter = Flatten<ArrayIter<Option<T>, N>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.arr.into_iter().flatten()
}
}
impl<T: Debug, const N: usize> Debug for ReArr<T, N> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("ReArr")
.field("arr", &self.arr)
.field("arr_len", &self.arr_len)
.finish()
}
}
impl<T: Debug, const N: usize> Display for ReArr<T, N> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_list().entries(self.arr.iter().flatten()).finish()
}
}