use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::slice;
struct NotSendSync(*const ());
pub struct FrameVec<'a, T> {
ptr: *mut T,
len: usize,
capacity: usize,
_marker: PhantomData<&'a mut T>,
_not_send_sync: PhantomData<NotSendSync>,
}
impl<'a, T> FrameVec<'a, T> {
pub(crate) unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Option<Self> {
if ptr.is_null() {
return None;
}
Some(Self {
ptr,
len: 0,
capacity,
_marker: PhantomData,
_not_send_sync: PhantomData,
})
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn remaining(&self) -> usize {
self.capacity - self.len
}
pub fn is_full(&self) -> bool {
self.len >= self.capacity
}
pub fn push(&mut self, value: T) -> Result<(), T> {
if self.is_full() {
return Err(value);
}
unsafe {
self.ptr.add(self.len).write(value);
}
self.len += 1;
Ok(())
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
self.len -= 1;
unsafe { Some(self.ptr.add(self.len).read()) }
}
pub fn get(&self, index: usize) -> Option<&T> {
if index >= self.len {
return None;
}
unsafe { Some(&*self.ptr.add(index)) }
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index >= self.len {
return None;
}
unsafe { Some(&mut *self.ptr.add(index)) }
}
pub fn clear(&mut self) {
for i in 0..self.len {
unsafe {
std::ptr::drop_in_place(self.ptr.add(i));
}
}
self.len = 0;
}
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
}
pub fn iter(&self) -> slice::Iter<'_, T> {
self.as_slice().iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
self.as_mut_slice().iter_mut()
}
pub fn extend_from_iter<I: IntoIterator<Item = T>>(&mut self, iter: I) -> usize {
let mut count = 0;
for item in iter {
if self.push(item).is_err() {
break;
}
count += 1;
}
count
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
let mut write = 0;
for read in 0..self.len {
unsafe {
let elem = &*self.ptr.add(read);
if f(elem) {
if write != read {
std::ptr::copy_nonoverlapping(self.ptr.add(read), self.ptr.add(write), 1);
}
write += 1;
} else {
std::ptr::drop_in_place(self.ptr.add(read));
}
}
}
self.len = write;
}
}
impl<'a, T> Deref for FrameVec<'a, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<'a, T> DerefMut for FrameVec<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl<'a, T> Index<usize> for FrameVec<'a, T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
self.get(index).expect("index out of bounds")
}
}
impl<'a, T> IndexMut<usize> for FrameVec<'a, T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.get_mut(index).expect("index out of bounds")
}
}
impl<'a, T> Drop for FrameVec<'a, T> {
fn drop(&mut self) {
self.clear();
}
}
impl<'a, T> IntoIterator for FrameVec<'a, T> {
type Item = T;
type IntoIter = FrameVecIntoIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
FrameVecIntoIter {
vec: self,
index: 0,
}
}
}
pub struct FrameVecIntoIter<'a, T> {
vec: FrameVec<'a, T>,
index: usize,
}
impl<'a, T> Iterator for FrameVecIntoIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.vec.len {
return None;
}
let item = unsafe { self.vec.ptr.add(self.index).read() };
self.index += 1;
Some(item)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.vec.len - self.index;
(remaining, Some(remaining))
}
}
impl<'a, T> ExactSizeIterator for FrameVecIntoIter<'a, T> {}
impl<'a, T> Drop for FrameVecIntoIter<'a, T> {
fn drop(&mut self) {
for i in self.index..self.vec.len {
unsafe {
std::ptr::drop_in_place(self.vec.ptr.add(i));
}
}
self.vec.len = 0;
}
}
pub struct FrameMap<'a, K, V> {
keys: *mut Option<K>,
values: *mut V,
len: usize,
capacity: usize,
_marker: PhantomData<&'a mut (K, V)>,
_not_send_sync: PhantomData<NotSendSync>,
}
impl<'a, K: Eq + std::hash::Hash, V> FrameMap<'a, K, V> {
pub(crate) unsafe fn from_raw_parts(
keys: *mut Option<K>,
values: *mut V,
capacity: usize,
) -> Option<Self> {
if keys.is_null() || values.is_null() {
return None;
}
for i in 0..capacity {
keys.add(i).write(None);
}
Some(Self {
keys,
values,
len: 0,
capacity,
_marker: PhantomData,
_not_send_sync: PhantomData,
})
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn capacity(&self) -> usize {
self.capacity
}
fn hash_index(&self, key: &K) -> usize {
use std::hash::Hasher;
let mut hasher = std::collections::hash_map::DefaultHasher::new();
key.hash(&mut hasher);
hasher.finish() as usize % self.capacity
}
pub fn insert(&mut self, key: K, value: V) -> Result<Option<V>, (K, V)> {
if self.len >= self.capacity * 3 / 4 {
return Err((key, value));
}
let mut index = self.hash_index(&key);
for _ in 0..self.capacity {
unsafe {
let slot = &mut *self.keys.add(index);
match slot {
None => {
*slot = Some(key);
self.values.add(index).write(value);
self.len += 1;
return Ok(None);
}
Some(k) if k == &key => {
let old = self.values.add(index).read();
self.values.add(index).write(value);
return Ok(Some(old));
}
_ => {
index = (index + 1) % self.capacity;
}
}
}
}
Err((key, value))
}
pub fn get(&self, key: &K) -> Option<&V> {
let mut index = self.hash_index(key);
for _ in 0..self.capacity {
unsafe {
let slot = &*self.keys.add(index);
match slot {
None => return None,
Some(k) if k == key => return Some(&*self.values.add(index)),
_ => {
index = (index + 1) % self.capacity;
}
}
}
}
None
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
let mut index = self.hash_index(key);
for _ in 0..self.capacity {
unsafe {
let slot = &*self.keys.add(index);
match slot {
None => return None,
Some(k) if k == key => return Some(&mut *self.values.add(index)),
_ => {
index = (index + 1) % self.capacity;
}
}
}
}
None
}
pub fn contains_key(&self, key: &K) -> bool {
self.get(key).is_some()
}
}
impl<'a, K, V> Drop for FrameMap<'a, K, V> {
fn drop(&mut self) {
for i in 0..self.capacity {
unsafe {
let slot = &mut *self.keys.add(i);
if slot.is_some() {
std::ptr::drop_in_place(slot);
std::ptr::drop_in_place(self.values.add(i));
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_frame_vec_basic() {
let mut buffer = [0u32; 16];
let mut vec = unsafe { FrameVec::from_raw_parts(buffer.as_mut_ptr(), 16).unwrap() };
assert!(vec.is_empty());
assert_eq!(vec.capacity(), 16);
vec.push(1).unwrap();
vec.push(2).unwrap();
vec.push(3).unwrap();
assert_eq!(vec.len(), 3);
assert_eq!(vec[0], 1);
assert_eq!(vec[1], 2);
assert_eq!(vec[2], 3);
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.len(), 2);
}
#[test]
fn test_frame_vec_full() {
let mut buffer = [0u32; 2];
let mut vec = unsafe { FrameVec::from_raw_parts(buffer.as_mut_ptr(), 2).unwrap() };
vec.push(1).unwrap();
vec.push(2).unwrap();
assert!(vec.push(3).is_err());
}
#[test]
fn test_frame_vec_iter() {
let mut buffer = [0u32; 16];
let mut vec = unsafe { FrameVec::from_raw_parts(buffer.as_mut_ptr(), 16).unwrap() };
vec.push(1).unwrap();
vec.push(2).unwrap();
vec.push(3).unwrap();
let sum: u32 = vec.iter().sum();
assert_eq!(sum, 6);
}
}