use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr;
use core::slice;
#[repr(C)]
pub(crate) struct KVec<T> {
pub(super) size: usize,
pub(super) capacity: usize,
pub(super) items: *mut T,
}
impl<T> Default for KVec<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for KVec<T> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T> KVec<T> {
#[inline]
pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
if self.items.is_null() {
&mut []
} else {
assert!(self.len() * mem::size_of::<T>() <= isize::MAX as usize);
unsafe { slice::from_raw_parts_mut(self.items, self.size) }
}
}
#[inline]
pub(crate) fn as_slice(&self) -> &[T] {
if self.items.is_null() {
&[]
} else {
assert!(self.len() * mem::size_of::<T>() <= isize::MAX as usize);
unsafe { slice::from_raw_parts(self.items, self.size) }
}
}
#[allow(dead_code)]
#[inline]
pub(crate) fn capacity(&self) -> usize {
self.capacity
}
#[inline]
pub(crate) fn len(&self) -> usize {
self.size
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub(crate) fn new() -> Self {
Self { items: core::ptr::null_mut(), size: 0, capacity: 0 }
}
#[inline]
pub(crate) fn push(&mut self, item: T) {
if self.capacity == 0 {
self.capacity = 4;
self.items = unsafe {
libc::malloc(self.capacity * mem::size_of::<T>()) as *mut T
};
} else if self.size == self.capacity {
self.capacity *= 2;
assert!(
self.capacity * mem::size_of::<T>() <= isize::MAX as usize
);
self.items = unsafe {
libc::realloc(
self.items as *mut libc::c_void,
self.capacity * mem::size_of::<T>(),
) as *mut T
};
}
unsafe {
ptr::write(self.items.add(self.size), item);
}
self.size += 1;
}
#[inline]
pub(crate) fn with_capacity(capacity: usize) -> Self {
let items =
unsafe { libc::malloc(capacity * mem::size_of::<T>()) as *mut T };
Self { items, size: 0, capacity }
}
}
impl<T: Clone> Clone for KVec<T> {
#[inline]
fn clone(&self) -> Self {
let items = unsafe {
libc::malloc(self.capacity * mem::size_of::<T>()) as *mut T
};
for idx in 0..self.size {
unsafe {
let item = &*self.items.add(idx);
ptr::write(items.add(idx), item.clone());
}
}
Self { items, size: self.size, capacity: self.capacity }
}
}
impl<T: PartialEq> PartialEq for KVec<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T> Deref for KVec<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> DerefMut for KVec<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T> FromIterator<T> for KVec<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lo, hi) = iter.size_hint();
let mut kvec = Self::with_capacity(hi.unwrap_or(lo));
for item in iter {
kvec.push(item);
}
kvec
}
}
impl<T> IntoIterator for KVec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
#[inline]
fn into_iter(self) -> IntoIter<T> {
let ptr = self.items;
let end = unsafe { ptr.add(self.size) };
mem::forget(self);
IntoIter { ptr, start: ptr, end }
}
}
impl<T> Drop for KVec<T> {
#[inline]
fn drop(&mut self) {
if !self.items.is_null() {
for idx in 0..self.size {
unsafe {
ptr::drop_in_place(self.items.add(idx));
}
}
unsafe { libc::free(self.items as *mut libc::c_void) };
}
}
}
pub(crate) struct IntoIter<T> {
ptr: *mut T,
start: *mut T,
end: *mut T,
}
impl<T: Clone> Clone for IntoIter<T> {
#[inline]
fn clone(&self) -> Self {
let len = unsafe { self.end.offset_from(self.start) as usize };
let ptr = unsafe { libc::malloc(len * mem::size_of::<T>()) as *mut T };
for idx in 0..len {
unsafe {
let item = &*self.start.add(idx);
ptr::write(ptr.add(idx), item.clone());
}
}
IntoIter { ptr, start: ptr, end: unsafe { ptr.add(len) } }
}
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.start == self.end {
None
} else {
let current = self.start;
self.start = unsafe { self.start.offset(1) };
Some(unsafe { ptr::read(current) })
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let exact = self.len();
(exact, Some(exact))
}
}
impl<T> ExactSizeIterator for IntoIter<T> {
#[inline]
fn len(&self) -> usize {
unsafe { self.end.offset_from(self.start) as usize }
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.start == self.end {
None
} else {
self.end = unsafe { self.end.offset(-1) };
Some(unsafe { ptr::read(self.end) })
}
}
}
impl<T> core::iter::FusedIterator for IntoIter<T> {}
impl<T> Drop for IntoIter<T> {
#[inline]
fn drop(&mut self) {
while self.start != self.end {
let current = self.start;
self.start = unsafe { self.start.offset(1) };
unsafe { ptr::drop_in_place(current) };
}
unsafe { libc::free(self.ptr as *mut libc::c_void) };
}
}
impl<T> From<Vec<T>> for KVec<T> {
#[inline]
fn from(vec: Vec<T>) -> Self {
vec.into_iter().collect()
}
}
impl<T> From<KVec<T>> for Vec<T> {
#[inline]
fn from(kvec: KVec<T>) -> Self {
kvec.into_iter().collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn kvec_as_slice() {
let mut kvec = KVec::new();
kvec.push("foo");
kvec.push("bar");
kvec.push("baz");
assert_eq!(kvec.as_slice(), &["foo", "bar", "baz"]);
}
#[test]
fn kvec_is_empty() {
let mut kvec = KVec::<&str>::new();
assert!(kvec.is_empty());
kvec.push("foo");
assert!(!kvec.is_empty());
}
#[test]
fn kvec_with_capacity() {
let kvec = KVec::<i32>::new();
assert_eq!(kvec.capacity(), 0);
let mut kvec = KVec::<i32>::with_capacity(2);
assert_eq!(kvec.capacity(), 2);
kvec.push(1);
kvec.push(2);
kvec.push(3);
assert_eq!(kvec.capacity(), 4);
}
#[test]
fn kvec_drop() {
let mut kvec = KVec::new();
kvec.push(String::from("foo"));
kvec.push(String::from("bar"));
kvec.push(String::from("baz"));
assert_eq!(kvec.len(), 3);
drop(kvec);
}
#[test]
fn kvec_clone() {
let mut kvec = KVec::new();
kvec.push(String::from("foo"));
kvec.push(String::from("bar"));
kvec.push(String::from("baz"));
let kvec2 = kvec.clone();
assert_eq!(kvec, kvec2);
drop(kvec);
drop(kvec2);
}
#[test]
fn kvec_from_iter() {
let kvec = vec!["foo", "bar", "baz"].into_iter().collect::<KVec<_>>();
assert_eq!(kvec.as_slice(), &["foo", "bar", "baz"]);
}
#[test]
fn kvec_into_iter() {
let kvec: KVec<String> =
["foo", "bar", "baz"].into_iter().map(Into::into).collect();
let mut iter = kvec.into_iter();
assert_eq!(Some("foo"), iter.next().as_deref());
assert_eq!(Some("bar"), iter.next().as_deref());
assert_eq!(Some("baz"), iter.next().as_deref());
assert_eq!(None, iter.next());
}
#[test]
fn kvec_iter_backward() {
let kvec: KVec<String> =
["foo", "bar", "baz"].into_iter().map(Into::into).collect();
let mut iter = kvec.into_iter();
assert_eq!(Some("baz"), iter.next_back().as_deref());
assert_eq!(Some("bar"), iter.next_back().as_deref());
assert_eq!(Some("foo"), iter.next_back().as_deref());
assert_eq!(None, iter.next_back());
}
#[test]
fn kvec_iter_drop_halfway() {
let kvec: KVec<String> =
["foo", "bar", "baz"].into_iter().map(Into::into).collect();
let mut iter = kvec.into_iter();
assert_eq!(Some("foo"), iter.next().as_deref());
assert_eq!(Some("bar"), iter.next().as_deref());
drop(iter);
}
#[test]
fn kvec_iter_clone() {
let kvec: KVec<String> =
["foo", "bar", "baz"].into_iter().map(Into::into).collect();
let mut iter = kvec.into_iter();
assert_eq!(Some("foo"), iter.next().as_deref());
let mut iter2 = iter.clone();
assert_eq!(Some("bar"), iter.next().as_deref());
assert_eq!(Some("baz"), iter.next().as_deref());
assert_eq!(None, iter.next());
assert_eq!(Some("bar"), iter2.next().as_deref());
assert_eq!(Some("baz"), iter2.next().as_deref());
assert_eq!(None, iter2.next());
}
}