#![cfg_attr(not(test), no_std)]
pub mod iter;
#[cfg(test)]
mod tests;
use core::cmp::Ordering;
use core::fmt::{self, Debug, Formatter};
use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, IntoIterator};
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
pub struct PartialArray<T, const N: usize> {
filled: usize,
array: [MaybeUninit<T>; N],
}
impl<T, const N: usize> Deref for PartialArray<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let slice = &self.array[..self.filled];
unsafe { mem::transmute(slice) }
}
}
impl<T, const N: usize> DerefMut for PartialArray<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
let slice = &mut self.array[..self.filled];
unsafe { mem::transmute(slice) }
}
}
impl<T: Debug, const N: usize> Debug for PartialArray<T, N> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
<[T] as Debug>::fmt(self, f)
}
}
impl<T: PartialEq, const N: usize, const M: usize> PartialEq<PartialArray<T, M>>
for PartialArray<T, N>
{
fn eq(&self, other: &PartialArray<T, M>) -> bool {
self.len() == other.len() && self.deref() == other.deref()
}
}
impl<T: PartialEq, const N: usize, const M: usize> PartialEq<[T; M]> for PartialArray<T, N> {
fn eq(&self, other: &[T; M]) -> bool {
self.len() == other.len() && self.deref() == other.deref()
}
}
impl<T: PartialEq, const N: usize, const M: usize> PartialEq<PartialArray<T, M>> for [T; N] {
fn eq(&self, other: &PartialArray<T, M>) -> bool {
self.len() == other.len() && self.deref() == other.deref()
}
}
impl<T: PartialEq, const N: usize> PartialEq<&[T]> for PartialArray<T, N> {
fn eq(&self, other: &&[T]) -> bool {
self.len() == other.len() && self.deref() == other.deref()
}
}
impl<T: PartialEq, const N: usize> PartialEq<PartialArray<T, N>> for &[T] {
fn eq(&self, other: &PartialArray<T, N>) -> bool {
self.len() == other.len() && self.deref() == other.deref()
}
}
impl<T: Eq, const N: usize> Eq for PartialArray<T, N> {}
impl<T, const N: usize> Default for PartialArray<T, N> {
fn default() -> Self {
Self {
array: [Self::UNINIT; N],
filled: 0,
}
}
}
impl<T: Hash, const N: usize> Hash for PartialArray<T, N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state);
}
}
impl<T: PartialOrd, const N: usize> PartialOrd for PartialArray<T, N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.deref().partial_cmp(other.deref())
}
}
impl<T: Ord, const N: usize> Ord for PartialArray<T, N> {
fn cmp(&self, other: &Self) -> Ordering {
self.deref().cmp(other.deref())
}
}
impl<T: Clone, const N: usize> Clone for PartialArray<T, N> {
fn clone(&self) -> Self {
self.iter().cloned().collect()
}
}
impl<T, const N: usize> Drop for PartialArray<T, N> {
fn drop(&mut self) {
(0..self.filled)
.map(|i| mem::replace(&mut self.array[i], Self::UNINIT))
.map(|entry| {
unsafe { entry.assume_init() }
})
.for_each(drop);
}
}
impl<T, const N: usize> PartialArray<T, N> {
const UNINIT: MaybeUninit<T> = MaybeUninit::uninit();
}
impl<T, const N: usize> FromIterator<T> for PartialArray<T, N> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut result = Self::default();
result.extend(iter);
result
}
}
impl<T, const N: usize> Extend<T> for PartialArray<T, N> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let remaining = (self.filled..N).len();
let mut iter = iter.into_iter();
iter.by_ref().take(remaining).for_each(|element| {
self.array[self.filled] = MaybeUninit::new(element);
self.filled += 1;
});
let remaining = iter.count();
assert_eq!(remaining, 0, "Iterator has {} elements to much", remaining);
}
}
impl<T, const N: usize> IntoIterator for PartialArray<T, N> {
type Item = T;
type IntoIter = iter::IntoIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
iter::IntoIter::new(self)
}
}
impl<T, const N: usize> From<[T; N]> for PartialArray<T, N> {
fn from(array: [T; N]) -> Self {
core::array::IntoIter::new(array).collect()
}
}
#[macro_export]
macro_rules! partial_array {
($($element:expr),*$(,)?) => {
$crate::PartialArray::from([$($element),*])
};
($element:expr; $n: literal) => {
$crate::PartialArray::from([$element; $n])
};
}