use ::core::{
fmt,
hint::unreachable_unchecked,
ptr,
};
use alloc::vec::Vec;
use super::Core;
pub struct OptionCore<T> {
data: Vec<Option<T>>,
}
impl<T> Core<T> for OptionCore<T> {
fn new() -> Self {
Self {
data: Vec::new(),
}
}
fn len(&self) -> usize {
self.data.len()
}
fn cap(&self) -> usize {
self.data.capacity()
}
unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.cap());
self.data.set_len(new_len)
}
#[inline(never)]
#[cold]
unsafe fn realloc(&mut self, new_cap: usize) {
debug_assert!(new_cap >= self.len());
debug_assert!(new_cap <= isize::max_value() as usize);
let old_cap = self.cap();
let initialized_end = if new_cap > old_cap {
let additional = new_cap - self.data.len();
self.data.reserve_exact(additional);
self.data.len()
} else if new_cap < old_cap {
let old_len = self.data.len();
self.data.set_len(new_cap);
self.data.shrink_to_fit();
self.data.set_len(old_len);
new_cap
} else {
self.data.capacity()
};
let actual_capacity = self.data.capacity();
let mut ptr = self.data.as_mut_ptr().add(initialized_end);
let end = self.data.as_mut_ptr().add(actual_capacity);
while ptr != end {
ptr::write(ptr, None);
ptr = ptr.add(1);
}
}
unsafe fn has_element_at(&self, idx: usize) -> bool {
debug_assert!(idx < self.cap());
(&*self.data.as_ptr().add(idx)).is_some()
}
unsafe fn insert_at(&mut self, idx: usize, elem: T) {
debug_assert!(idx < self.cap());
debug_assert!(self.has_element_at(idx) == false);
ptr::write(self.data.as_mut_ptr().add(idx), Some(elem));
}
unsafe fn remove_at(&mut self, idx: usize) -> T {
debug_assert!(idx < self.cap());
debug_assert!(self.has_element_at(idx));
match self.data.get_unchecked_mut(idx).take() {
None => unreachable_unchecked(),
Some(elem) => elem,
}
}
unsafe fn get_unchecked(&self, idx: usize) -> &T {
debug_assert!(idx < self.cap());
debug_assert!(self.has_element_at(idx));
match self.data.get_unchecked(idx) {
None => unreachable_unchecked(),
Some(elem) => elem,
}
}
unsafe fn get_unchecked_mut(&mut self, idx: usize) -> &mut T {
debug_assert!(idx < self.cap());
debug_assert!(self.has_element_at(idx));
match self.data.get_unchecked_mut(idx) {
None => unreachable_unchecked(),
Some(elem) => elem,
}
}
fn clear(&mut self) {
for item in self.data.iter_mut() {
drop(item.take());
}
unsafe {
self.set_len(0);
}
}
unsafe fn swap(&mut self, a: usize, b: usize) {
let p = self.data.as_mut_ptr();
let pa: *mut _ = p.add(a);
let pb: *mut _ = p.add(b);
ptr::swap(pa, pb);
}
}
impl<T: Clone> Clone for OptionCore<T> {
fn clone(&self) -> Self {
let mut data = Vec::with_capacity(self.data.capacity());
data.extend(
self.data
.iter()
.cloned()
.chain(core::iter::repeat(None).take(self.data.capacity() - self.data.len())),
);
debug_assert_eq!(data.len(), self.data.capacity());
debug_assert_eq!(data.capacity(), self.data.capacity());
unsafe {
data.set_len(self.data.len());
}
Self { data }
}
}
impl<T> Drop for OptionCore<T> {
fn drop(&mut self) {
}
}
impl<T: fmt::Debug> fmt::Debug for OptionCore<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("OptionCore")
.field(&self.data)
.finish()
}
}