#[cfg(test)]
mod tests;
use libc::*;
use std::alloc::{dealloc, Layout};
use std::mem;
pub struct Bucket<T> {
content_ptr: *mut T,
}
impl<T> Bucket<T> {
pub fn new(content: T) -> Self {
let bucket = Self::default();
unsafe {
std::ptr::write(bucket.content_ptr, content);
}
bucket
}
pub fn vacate(&self) -> Option<T> {
if self.is_empty() {
return None;
}
let content;
unsafe {
content = std::ptr::read::<T>(self.content_ptr as *const _);
memset(self.content_ptr as *mut _, 0, Self::size());
};
Some(content)
}
pub fn peek_ref(&self) -> Option<&T> {
if self.is_empty() {
return None;
}
unsafe { Some(&*self.content_ptr) }
}
pub fn peek_mut(&self) -> Option<&mut T> {
if self.is_empty() {
return None;
}
unsafe { Some(&mut *self.content_ptr) }
}
pub fn fill(&self, content: T) -> Option<T> {
if !self.is_empty() {
return Some(content);
}
unsafe {
std::ptr::write(self.content_ptr, content);
}
None
}
pub fn is_empty(&self) -> bool {
for i in 0..Self::size() {
let byte = (self.content_ptr as usize + i) as *const u8;
unsafe {
if *byte != 0 {
return false;
}
}
}
true
}
#[inline]
const fn size() -> usize {
mem::size_of::<T>()
}
fn dealloc(ptr: *mut T) {
unsafe {
dealloc(ptr as *mut _, Layout::new::<T>());
}
}
}
impl<T> Default for Bucket<T> {
fn default() -> Self {
Self {
content_ptr: unsafe {
let ptr = malloc(Self::size()) as *mut T;
memset(ptr as *mut _, 0, Self::size());
ptr
},
}
}
}
impl<T> Drop for Bucket<T> {
fn drop(&mut self) {
Bucket::dealloc(self.content_ptr);
}
}