use core::array;
use core::fmt;
use core::mem::{self, MaybeUninit};
use core::iter::FusedIterator;
use core::ops::{Deref, DerefMut};
use super::Group;
pub struct Carry<T, const N: usize> {
buf: [MaybeUninit<T>; N],
len: usize,
}
impl<T, const N: usize> Carry<T, N> {
const N_IS_NONZERO: () = assert!(N > 0, "'Carry<T, 0>' is invalid!");
pub fn new() -> Self {
let _ = Self::N_IS_NONZERO;
Self {
buf: array::from_fn(|_| MaybeUninit::uninit()),
len: 0,
}
}
pub fn push(&mut self, elem: T) -> Option<[T; N]> {
unsafe { self.buf.get_unchecked_mut(self.len) }.write(elem);
self.len += 1;
(self.len == N).then(|| {
let buf = mem::take(self).into_raw_parts().0;
buf.map(|e| unsafe { MaybeUninit::assume_init(e) })
})
}
pub fn append(&mut self, elems: Self) -> Option<[T; N]> {
let mut iter = elems.into_iter();
let result = self.extend(&mut iter);
let excess = self.extend(&mut iter);
debug_assert!(excess.is_none());
debug_assert!(iter.next().is_none());
result
}
pub fn append_group(&mut self, elems: Group<T, N>) -> Option<[T; N]> {
let mut iter = elems.into_iter();
let result = self.extend(&mut iter);
let excess = self.extend(&mut iter);
debug_assert!(excess.is_none());
debug_assert!(iter.next().is_none());
result
}
pub fn append_array(&mut self, elems: [T; N]) -> Option<[T; N]> {
let mut iter = elems.into_iter();
let result = self.extend(&mut iter);
let excess = self.extend(&mut iter);
debug_assert!(excess.is_none());
debug_assert!(iter.next().is_none());
result
}
pub fn extend<I>(&mut self, elems: &mut I) -> Option<[T; N]>
where I: Iterator<Item = T> {
for d in unsafe { self.buf.get_unchecked_mut(self.len ..) } {
d.write(elems.next()?);
self.len += 1;
}
let buf = mem::take(self).into_raw_parts().0;
Some(buf.map(|e| unsafe { MaybeUninit::assume_init(e) }))
}
pub fn extend_copying<'a, I>(&mut self, elems: &mut I) -> Option<[T; N]>
where T: 'a + Copy, I: Iterator<Item = &'a T> {
for d in unsafe { self.buf.get_unchecked_mut(self.len ..) } {
d.write(*elems.next()?);
self.len += 1;
}
let buf = mem::replace(self, Self::new()).buf;
Some(buf.map(|e| unsafe { MaybeUninit::assume_init(e) }))
}
pub fn drain(&mut self) -> Drain<'_, T, N> {
Drain {
beg: 0,
end: mem::replace(&mut self.len, 0),
buf: &mut self.buf,
}
}
pub fn into_raw_parts(mut self) -> ([MaybeUninit<T>; N], usize) {
let buf = array::from_fn(|_| MaybeUninit::uninit());
let buf = mem::replace(&mut self.buf, buf);
let len = mem::replace(&mut self.len, 0);
(buf, len)
}
}
impl<T, const N: usize> Default for Carry<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Drop for Carry<T, N> {
fn drop(&mut self) {
let buf = unsafe { self.buf.get_unchecked_mut(0 .. self.len) };
buf.iter_mut().for_each(|v| unsafe { v.assume_init_drop() });
self.len = 0;
}
}
impl<T: Clone, const N: usize> Clone for Carry<T, N> {
fn clone(&self) -> Self {
let buf = array::from_fn(|i| {
self.buf.get(i)
.map(|e| unsafe { e.assume_init_ref() }.clone())
.map_or(MaybeUninit::uninit(), MaybeUninit::new)
});
Self { buf, len: self.len }
}
}
impl<T, const N: usize> IntoIterator for Carry<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
let (buf, len) = self.into_raw_parts();
IntoIter { beg: 0, end: len, buf }
}
}
impl<T, const N: usize> Deref for Carry<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let buf = unsafe { self.buf.get_unchecked(0 .. self.len) };
unsafe { mem::transmute(buf) }
}
}
impl<T, const N: usize> DerefMut for Carry<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
let buf = unsafe { self.buf.get_unchecked_mut(0 .. self.len) };
unsafe { mem::transmute(buf) }
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for Carry<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}
pub struct IntoIter<T, const N: usize> {
beg: usize,
end: usize,
buf: [MaybeUninit<T>; N],
}
impl<T, const N: usize> Drop for IntoIter<T, N> {
fn drop(&mut self) {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
buf.iter_mut().for_each(|v| unsafe { v.assume_init_drop() });
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.beg >= self.end { return None; }
let elem = unsafe { self.buf.get_unchecked_mut(self.beg) };
let elem = mem::replace(elem, MaybeUninit::uninit());
self.beg += 1;
Some(unsafe { elem.assume_init() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.end - self.beg, Some(self.end - self.beg))
}
fn count(self) -> usize {
self.end - self.beg
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
fn for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().for_each(|elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(unsafe { elem.assume_init() })
})
}
fn fold<B, F: FnMut(B, Self::Item) -> B>(mut self, init: B, mut f: F) -> B {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().fold(init, |state, elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(state, unsafe { elem.assume_init() })
})
}
}
impl<'a, T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.end >= self.beg { return None; }
self.end -= 1;
let elem = unsafe { self.buf.get_unchecked_mut(self.end) };
let elem = mem::replace(elem, MaybeUninit::uninit());
Some(unsafe { elem.assume_init() })
}
fn rfold<B, F: FnMut(B, Self::Item) -> B>(mut self, init: B, mut f: F) -> B {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().rfold(init, |state, elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(state, unsafe { elem.assume_init() })
})
}
}
impl<'a, T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
fn len(&self) -> usize {
self.end - self.beg
}
}
impl<'a, T, const N: usize> FusedIterator for IntoIter<T, N> {}
pub struct Drain<'a, T, const N: usize> {
buf: &'a mut [MaybeUninit<T>; N],
beg: usize,
end: usize,
}
impl<'a, T, const N: usize> Drop for Drain<'a, T, N> {
fn drop(&mut self) {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
buf.iter_mut().for_each(|v| unsafe { v.assume_init_drop() });
}
}
impl<'a, T, const N: usize> Iterator for Drain<'a, T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.beg >= self.end { return None; }
let elem = unsafe { self.buf.get_unchecked_mut(self.beg) };
let elem = mem::replace(elem, MaybeUninit::uninit());
self.beg += 1;
Some(unsafe { elem.assume_init() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.end - self.beg, Some(self.end - self.beg))
}
fn count(self) -> usize {
self.end - self.beg
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
fn for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().for_each(|elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(unsafe { elem.assume_init() })
})
}
fn fold<B, F: FnMut(B, Self::Item) -> B>(mut self, init: B, mut f: F) -> B {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().fold(init, |state, elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(state, unsafe { elem.assume_init() })
})
}
}
impl<'a, T, const N: usize> DoubleEndedIterator for Drain<'a, T, N> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.end >= self.beg { return None; }
self.end -= 1;
let elem = unsafe { self.buf.get_unchecked_mut(self.end) };
let elem = mem::replace(elem, MaybeUninit::uninit());
Some(unsafe { elem.assume_init() })
}
fn rfold<B, F: FnMut(B, Self::Item) -> B>(mut self, init: B, mut f: F) -> B {
let buf = unsafe { self.buf.get_unchecked_mut(self.beg .. self.end) };
self.beg = self.end;
buf.iter_mut().rfold(init, |state, elem| {
let elem = mem::replace(elem, MaybeUninit::uninit());
(f)(state, unsafe { elem.assume_init() })
})
}
}
impl<'a, T, const N: usize> ExactSizeIterator for Drain<'a, T, N> {
fn len(&self) -> usize {
self.end - self.beg
}
}
impl<'a, T, const N: usize> FusedIterator for Drain<'a, T, N> {}