mod allocator;
pub mod const_raw_ptr {
use std::marker::{Copy, Send, Sync};
pub struct ConstRawPtr<T>
where T: Sized + Copy + Send + Sync
{
ptr: *const T,
memory_length: usize,
offset: usize,
}
impl<T: Sized + Copy + Send + Sync> ConstRawPtr<T> {
pub unsafe fn c_malloc(data: Vec<T>, memory_length: usize, offset: usize) -> Option<ConstRawPtr<T>> {
if memory_length == 0 || offset >= memory_length || data.len() == 0 || data.len() > memory_length {
return None;
}
let size: usize = std::mem::size_of::<T>() * memory_length;
let align: usize = std::mem::align_of::<T>();
let layout: std::alloc::Layout = std::alloc::Layout::from_size_align(size, align).expect("Invalid alignment or size parameters.");
unsafe {
let alloc: *mut T = std::alloc::alloc(layout) as *mut T;
if alloc.is_null() {
return None;
}
for (idx, value) in data.into_iter().enumerate() {
std::ptr::write(alloc.add(idx), value);
}
Some(ConstRawPtr::new(alloc as *const T, memory_length, offset))
}
}
#[inline]
pub fn new(ptr: *const T, memory_length: usize, offset: usize) -> Self {
assert!((ptr as usize) % std::mem::align_of::<T>() == 0, "box_raw_ptr Err: Memory Not Aligned");
assert!(offset < memory_length, "box_raw_ptr Err: Offset Is Not Within Bounds");
Self { ptr, memory_length, offset, }
}
#[inline]
pub fn nullptr() -> Self {
Self { ptr: std::ptr::null(), memory_length: 0, offset: 0 }
}
#[inline]
pub unsafe fn manual_drop(self) -> () {
drop(self);
}
#[inline]
pub fn check_bounds(&self) -> bool {
(0..=self.memory_length).contains(&self.offset)
}
pub fn check_ptr(&self) -> bool {
if self.ptr.is_null() {
return false;
}
let align: usize = std::mem::align_of::<T>();
(self.ptr as usize) % align == 0
}
pub fn check_offset(&self) -> usize {
self.offset
}
pub fn check_memory_length(&self) -> usize {
self.memory_length
}
pub fn change_offset(&mut self, offset: isize) -> Option<()> {
if !self.check_ptr() {
return None;
}
let new_offset: isize = self.offset as isize + offset;
if new_offset >= 0 && new_offset < self.memory_length as isize {
let new_ptr: *const T = unsafe { self.ptr.byte_offset(offset) };
self.offset = new_offset as usize;
self.ptr = new_ptr;
Some(())
} else {
None
}
}
pub unsafe fn change_memory_length(&mut self, memory_length: usize) -> Option<()> {
if memory_length <= 0 || self.offset >= memory_length {
return None;
}
self.memory_length = memory_length;
Some(())
}
pub fn release_ptr(self) -> Option<T> {
if self.check_ptr() {
unsafe {
let ptr: T = *self.ptr;
drop(self);
Some(ptr)
}
} else {
None
}
}
#[inline]
pub fn set_null(&mut self) -> () {
if self.check_ptr() {
self.memory_length = 0;
self.offset = 0;
self.ptr = std::ptr::null();
}
}
#[inline]
pub fn memory_address(&self) -> usize {
self.ptr as usize
}
#[inline]
pub fn as_mut(&self) -> super::mut_raw_ptr::MutRawPtr<T> {
super::mut_raw_ptr::MutRawPtr::new(self.ptr as *mut T, self.memory_length, self.offset)
}
pub fn access(&self) -> Option<T> {
if self.check_ptr() {
Some( unsafe { *self.ptr } )
} else {
None
}
}
pub fn ref_const(&self) -> Option<&T> {
if self.check_ptr() {
Some( unsafe { & *self.ptr } )
} else {
None
}
}
#[inline]
pub fn is_null(&self) -> bool {
self.ptr.is_null()
}
#[inline]
pub fn size_of() -> usize {
std::mem::size_of::<T>()
}
pub fn cast_ptr<U: Sized + Copy + Send + Sync>(&self) -> Option<ConstRawPtr<U>> {
if !self.ptr.is_null() {
Some(ConstRawPtr {
ptr: self.ptr as *const U, memory_length: self.memory_length, offset: self.offset
})
} else {
None
}
}
}
impl<T: Sized + Copy + Send + Sync> Clone for ConstRawPtr<T> {
fn clone(&self) -> Self {
Self { ptr: self.ptr.clone(), memory_length: self.memory_length, offset: self.offset }
}
}
impl<T: Sized + Copy + Send + Sync> Drop for ConstRawPtr<T> {
fn drop(&mut self) {
if self.check_ptr() {
unsafe {
let layout: std::alloc::Layout = std::alloc::Layout::new::<T>();
std::alloc::dealloc(self.ptr as *mut u8, layout);
}
}
}
}
}
pub mod mut_raw_ptr {
use std::marker::{Copy, Send, Sync};
pub struct MutRawPtr<T>
where T: Sized + Copy + Clone + Send + Sync
{
ptr: *mut T,
memory_length: usize,
offset: usize,
}
impl<T: Sized + Copy + Clone + Send + Sync> MutRawPtr<T> {
pub unsafe fn c_malloc(data: Vec<T>, memory_length: usize, offset: usize) -> Option<MutRawPtr<T>> {
if memory_length == 0 || offset >= memory_length || data.len() == 0 || data.len() > memory_length {
return None;
}
let size: usize = std::mem::size_of::<T>() * memory_length;
let align: usize = std::mem::align_of::<T>();
let layout: std::alloc::Layout = std::alloc::Layout::from_size_align(size, align).expect("Invalid alignment or size parameters.");
unsafe {
let alloc: *mut T = std::alloc::alloc(layout) as *mut T;
if alloc.is_null() {
return None;
}
for (idx, value) in data.into_iter().enumerate() {
std::ptr::write(alloc.add(idx), value);
}
Some(MutRawPtr::new(alloc, memory_length, offset))
}
}
#[inline]
pub fn new(ptr: *mut T, memory_length: usize, offset: usize) -> Self {
assert!((ptr as usize) % std::mem::align_of::<T>() == 0, "box_raw_ptr Err: Memory Not Aligned");
assert!(offset < memory_length, "box_raw_ptr Err: Offset Is Not Within Bounds");
Self { ptr, memory_length, offset, }
}
#[inline]
pub fn nullptr() -> Self {
Self { ptr: std::ptr::null_mut(), memory_length: 0, offset: 0 }
}
#[inline]
pub unsafe fn manual_drop(self) -> () {
drop(self);
}
#[inline]
pub fn check_bounds(&self) -> bool {
(0..=self.memory_length).contains(&self.offset)
}
pub fn check_ptr(&self) -> bool {
if self.ptr.is_null() {
return false;
}
let align: usize = std::mem::align_of::<T>();
(self.ptr as usize) % align == 0
}
pub fn check_offset(&self) -> usize {
self.offset
}
pub fn check_memory_length(&self) -> usize {
self.memory_length
}
pub fn change_offset(&mut self, offset: isize) -> Option<()> {
if !self.check_ptr() {
return None;
}
let new_offset: isize = self.offset as isize + offset;
if new_offset >= 0 && new_offset < self.memory_length as isize {
let new_ptr: *mut T = unsafe { self.ptr.byte_offset(offset) };
self.offset = new_offset as usize;
self.ptr = new_ptr;
Some(())
} else {
None
}
}
pub fn change_memory_length(&mut self, memory_length: usize) -> Option<()> {
if memory_length <= 0 || self.offset > memory_length {
return None;
}
self.memory_length = memory_length;
Some(())
}
pub fn release_ptr(self) -> Option<T> {
if self.check_ptr() {
unsafe {
let ptr: T = *self.ptr;
drop(self);
Some(ptr)
}
} else {
None
}
}
#[inline]
pub fn set_null(&mut self) -> () {
if self.check_ptr() {
self.memory_length = 0;
self.offset = 0;
self.ptr = std::ptr::null_mut();
}
}
#[inline]
pub fn memory_address(&self) -> usize {
self.ptr as usize
}
pub fn as_const(&self) -> super::const_raw_ptr::ConstRawPtr<T> {
super::const_raw_ptr::ConstRawPtr::new(self.ptr as *const T, self.memory_length, self.offset)
}
pub fn access(&self) -> Option<T> {
if self.check_ptr() {
Some( unsafe { *self.ptr } )
} else {
None
}
}
pub fn ref_const(&self) -> Option<&T> {
if self.check_ptr() {
Some( unsafe { & *self.ptr } )
} else {
None
}
}
pub fn ref_mut(&self) -> Option<&mut T> {
if self.check_ptr() {
unsafe { Some(&mut *self.ptr) }
} else {
None
}
}
#[inline]
pub fn is_null(&self) -> bool {
self.ptr.is_null()
}
#[inline]
pub fn size_of(&self) -> usize {
std::mem::size_of::<T>()
}
pub fn cast_ptr<U: Sized + Copy + Send + Sync>(&self) -> Option<MutRawPtr<U>> {
if !self.ptr.is_null() {
Some(MutRawPtr {
ptr: self.ptr as *mut U,
memory_length: self.memory_length,
offset: self.offset,
})
} else {
None
}
}
pub fn write_ptr(&mut self, src: T) -> Option<()> {
if !self.check_ptr() {
return None;
}
unsafe {
std::ptr::write(self.ptr, src);
}
Some(())
}
}
impl<T: Sized + Copy + Send + Sync> Clone for MutRawPtr<T> {
fn clone(&self) -> Self {
Self { ptr: self.ptr.clone(), memory_length: self.memory_length, offset: self.offset }
}
}
impl<T: Sized + Copy + Send + Sync> Drop for MutRawPtr<T> {
fn drop(&mut self) {
if self.check_ptr() {
unsafe {
let layout: std::alloc::Layout = std::alloc::Layout::new::<T>();
std::alloc::dealloc(self.ptr as *mut u8, layout);
}
}
}
}
}
#[cfg(test)]
mod box_raw_ptr_tests {
use super::mut_raw_ptr::MutRawPtr;
#[test]
fn c_allocator_test() -> () {
let alloc: *mut _ = unsafe { std::alloc::alloc(std::alloc::Layout::new::<i32>()) as *mut i32 };
let _ = MutRawPtr::new(alloc, 1, 0);
}
}