box_raw_ptr/
lib.rs

1/*
2*       ____             ____                 ____  __      
3*      / __ )____  _  __/ __ \____ __      __/ __ \/ /______
4*     / __  / __ \| |/_/ /_/ / __ `/ | /| / / /_/ / __/ ___/
5*    / /_/ / /_/ />  </ _, _/ /_/ /| |/ |/ / ____/ /_/ /    
6*   /_____/\____/_/|_/_/ |_|\__,_/ |__/|__/_/    \__/_/     
7*                                               
8*   
9*   Copyright (c) 2024 Rocco Zinedine Samuel Jenson
10*   
11*   Licensed under the MIT License (the "License");
12*   you may not use this file except in compliance with the License.
13*   You may obtain a copy of the License at
14*
15*   https://opensource.org/licenses/MIT
16*   
17*   Unless required by applicable law or agreed to in writing, software
18*   distributed under the License is distributed on an "AS IS" BASIS,
19*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20*   See the License for the specific language governing permissions and
21*   limitations under the License.
22*/
23
24//! # box_raw_ptr
25//!
26//! box_raw_ptr is a Rust library providing safe abstractions for working with raw pointers (`*const T` and `*mut T`). It ensures proper alignment, bounds checking, and safe memory operations, inspired by Rust's safety principles while allowing interoperability with C-style memory management. NOTE: It is still the user's responcibilty to correctly handle input of length and offset. 
27//!
28//! ## Features
29//!
30//! - **Type Safety**: Wrappers (`ConstRawPtr` and `MutRawPtr`) ensure safe usage of raw pointers (`*const T` and `*mut T`).
31//!
32//! - **Bounds Checking**: Methods to check and adjust offsets within allocated memory.
33//!
34//! - **Alignment Guarantees**: Ensures pointers are aligned according to `T`.
35//!
36//! - **Memory Management**: Includes methods for deallocating memory and safely handling null pointers.
37//!
38//! - **Interoperability**: Facilitates safe interaction with memory allocated by C functions or Rust's allocator.
39//!
40//! ## Components
41//!
42//! - **ConstRawPtr**: Provides safe operations on `*const T` pointers, including bounds checking and memory release.
43//!
44//! - **MutRawPtr**: Offers safe operations on `*mut T` pointers, supporting mutable access and memory management.
45//!
46//! ## Usage
47//!
48//! ```rust
49//! use box_raw_ptr::mut_raw_ptr::MutRawPtr; // Import MutRawPtr from box_raw_ptr
50//!
51//! #[link(name = "example", kind = "static")] // Link to a static library "example"
52//! extern "C" { // Declare C functions
53//!     fn c_ptr() -> *mut Data; // Declare C function returning a pointer to Data
54//!     fn c_ptr2() -> *mut std::ffi::c_int; // Declare C function returning a pointer to std::ffi::c_int
55//! }
56//!
57//! #[repr(C)] // Make Data a C-compatible struct
58//! #[derive(Clone, Copy)] // Derive Copy and Clone traits for Data
59//! struct Data { // Define a struct to represent data
60//!     a: i32, // Field of type i32
61//!     b: f64, // Field of type f64
62//! }
63//!
64//! fn main() { // Main function starts here
65//!     // Example: Import C pointer and write to the allocated data
66//!     let mut safeptr: MutRawPtr<Data> = MutRawPtr::new(unsafe { c_ptr() }, /*# of Data Blocks*/ 1, /*offset*/ 0); // Create MutRawPtr with the C pointer
67//!
68//!     assert_eq!(16, safeptr.size_of()); // Assert the size of Data is 16 bytes
69//!
70//!     safeptr.write_ptr(Data {a: 100, b: 12.0}); // Write to the memory pointed by safeptr
71//!
72//!     assert_eq!(100, (safeptr.access().unwrap()).a); // Assert the written value
73//!
74//!     // Example: Iteratively Rewrite Values in a Block Of Data (Assuming 5 Blocks of i32)
75//!     let mut safeptr: MutRawPtr<_> = MutRawPtr::new( unsafe { c_ptr2() }, 5, 0); // Create MutRawPtr with another C pointer
76//!
77//!     for i in 0..=4 { // Iterate 5 times
78//!                       /* change_offset() is byte indexed */
79//!         safeptr.change_offset(i * std::mem::size_of::<i32>()).unwrap();
80//!         safeptr.write_ptr(100 as i32).unwrap(); // Write a value (100) to the current memory location
81//!         println!("{}", safeptr.access().unwrap()); // Print the value at the current offset
82//!     }
83//! }
84//!
85//! ```
86//!
87//! ## Safety Considerations
88//!
89//! - **Unsafe Contexts**: Use of raw pointers inherently involves unsafe operations.
90//!
91//! - **Memory Safety**: Ensure proper initialization and alignment of pointers.
92//!
93//! - **Dropping Pointers**: Manually dropping pointers can lead to undefined behavior if used afterward.
94//!
95//! ## Installation
96//!
97//! Add the following to your `Cargo.toml`:
98//!
99//! ```toml
100//! [dependencies]
101//! box_raw_ptr = "2.2.0"
102//! ```
103//!
104//! ## Documentation
105//!
106//! For detailed API documentation, refer to [docs.rs](https://docs.rs/box_raw_ptr/latest/box_raw_ptr/).
107//!
108//! ## License
109//!
110//! MIT License
111//!
112//! Copyright (c) 2024 Rocco Zinedine Samuel Jenson
113//!
114//! Permission is hereby granted, free of charge, to any person obtaining a copy
115//! of this software and associated documentation files (the "Software"), to deal
116//! in the Software without restriction, including without limitation the rights
117//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
118//! copies of the Software, and to permit persons to whom the Software is
119//! furnished to do so, subject to the following conditions:
120//!
121//! The above copyright notice and this permission notice shall be included in all
122//! copies or substantial portions of the Software.
123//!
124//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
125//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
126//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
127//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
128//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
129//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
130//! SOFTWARE.
131
132/* 
133Imports C_Global_Allocator to library
134See allocator.rs and allocator.c for implementation
135Note: ALL LIBRARY HEAP ALLOCATIONS MANAGED BY MALLOC AND FREE
136*/
137mod allocator;
138
139pub mod const_raw_ptr {
140    use std::marker::{Copy, Send, Sync};
141
142    /// A wrapper for `*const T` providing methods for safely working with constant raw pointers.
143    /// 
144    /// `ConstRawPtr` ensures that the raw pointer is properly aligned and provides utility methods
145    /// for checking bounds, changing offsets, and other common pointer operations. 
146    ///
147    /// Fields:
148    /// - `ptr: *const T`: A raw constant pointer to the data.
149    /// - `memory_length: usize`: The length of the memory block in elements of T that `ptr` points to.
150    /// - `offset: usize`: The current position within the memory block.
151    ///
152    /// Notes:
153    /// - `memory_length` is not zero-based indexed.
154    /// - `offset` is zero-based indexed.
155    ///
156    /// # Safety
157    ///
158    /// Working with raw pointers is inherently unsafe. Ensure that the memory pointed to by `ptr` is valid 
159    /// and properly aligned before using this struct.
160    pub struct ConstRawPtr<T> 
161    where  T: Sized + Copy + Send + Sync
162    {
163        ptr: *const T,
164        memory_length: usize,
165        offset: usize,
166    }
167
168    impl<T: Sized + Copy + Send + Sync> ConstRawPtr<T> {
169        /// Allocates memory for an array of `memory_length` elements of type `T` and returns a const raw pointer to the allocated memory.
170        ///
171        /// # Parameters
172        ///
173        /// - `memory_length`: The number of elements of type `T` to allocate memory for. Must be greater than 0.
174        /// - `offset`: The initial offset within the allocated memory, typically starting at 0.
175        /// - `data`: A vector of values of type `T` that will be written to the newly allocated memory. The number of elements in `data` must not exceed `memory_length`, and the vector cannot be empty.
176        ///
177        /// # Returns
178        ///
179        /// - `Some(ConstRawPtr<T>)`: A const raw pointer to the allocated memory if the allocation is successful and the data is written correctly.
180        /// - `None`: If `memory_length` is 0 or less, or if the data vector is not within the bounds of the allocated memory (either because it is empty or has more elements than `memory_length`).
181        ///
182        /// # Panics
183        ///
184        /// This function may panic if the alignment or size parameters are invalid. Specifically, the following conditions may cause a panic:
185        /// - Alignment being zero or not a power of two.
186        /// - The size, when rounded up to the nearest multiple of alignment, overflows `isize` (i.e., the rounded value must be less than or equal to `isize::MAX`).
187        ///
188        /// # Safety
189        ///
190        /// This function is marked `unsafe` because it performs raw memory allocation. The caller is responsible for ensuring that:
191        /// - The memory is properly initialized and used correctly.
192        /// - Proper alignment and size are provided, as invalid values may cause undefined behavior.
193        /// - The `data` vector contains values that will be written to the allocated memory safely, as raw pointer operations do not include bounds checking.
194        ///
195        /// # Example
196        ///
197        /// ```rust
198        /// let alloc: *const i32 = unsafe { 
199        ///     ConstRawPtr::c_malloc(vec![1, 2, 3], 5, 1).unwrap(); 
200        /// };
201        /// ```
202        pub unsafe fn c_malloc(data: Vec<T>, memory_length: usize, offset: usize) -> Option<ConstRawPtr<T>> {
203            if memory_length == 0 || offset >= memory_length || data.len() == 0 || data.len() > memory_length {
204                return None;
205            }
206
207            let size: usize = std::mem::size_of::<T>() * memory_length;
208            let align: usize = std::mem::align_of::<T>();
209            let layout: std::alloc::Layout = std::alloc::Layout::from_size_align(size, align).expect("Invalid alignment or size parameters.");
210
211            unsafe {
212                let alloc: *mut T = std::alloc::alloc(layout) as *mut T;
213                
214                if alloc.is_null() {
215                    return None;
216                }
217
218                for (idx, value) in data.into_iter().enumerate() {
219                    std::ptr::write(alloc.add(idx), value);
220                }
221
222                Some(ConstRawPtr::new(alloc as *const T, memory_length, offset))
223            }
224        }
225
226        /// Creates a new `ConstRawPtr` with the given pointer, memory length, and offset. Make sure the length and offset are correct from C or std::alloc
227        /// 
228        /// This method ensures that the pointer is properly aligned and that the offset is within the bounds 
229        /// of the allocated memory length.
230        /// 
231        /// # Panics
232        /// 
233        /// Panics if the pointer is not aligned to `T` or if the offset is not within the bounds of the memory length.
234        /// 
235        /// # Examples
236        /// 
237        /// ```rust
238        /// let alloc_ptr: *const i32 = ...; // Assume this is a properly allocated and aligned pointer either from C or using Rust's std::alloc::alloc and std::alloc::Layout otherwise it will panic.
239        /// let ptr = ConstRawPtr::new(alloc_ptr, 1, 1);
240        /// ```
241        #[inline]
242        pub fn new(ptr: *const T, memory_length: usize, offset: usize) -> Self {
243            assert!((ptr as usize) % std::mem::align_of::<T>() == 0, "box_raw_ptr Err: Memory Not Aligned");
244            assert!(offset < memory_length, "box_raw_ptr Err: Offset Is Not Within Bounds");
245            Self { ptr, memory_length, offset, }
246        }
247
248        /// Creates a new `ConstRawPtr` with a null pointer and zero memory length and offset.
249        /// 
250        /// This is useful for creating a placeholder `ConstRawPtr` that can later be assigned a valid pointer.
251        /// 
252        /// # Examples
253        /// 
254        /// ```rust
255        /// let null_ptr = ConstRawPtr::<i32>::nullptr();
256        /// ```
257        #[inline]
258        pub fn nullptr() -> Self {
259            Self { ptr: std::ptr::null(), memory_length: 0, offset: 0 }
260        }
261
262        /// Manually drops the `ConstRawPtr` instance.
263        /// 
264        /// # Safety
265        /// 
266        /// This function is unsafe because it drops the instance manually, which can lead to undefined behavior 
267        /// if the instance is used after being dropped.
268        /// 
269        /// # Examples
270        /// 
271        /// ```rust
272        /// unsafe {
273        ///     ptr.manual_drop();
274        /// }
275        /// ```
276        #[inline]
277        pub unsafe fn manual_drop(self) -> () {
278            drop(self);
279        }
280
281        /// Checks if the current offset is within the bounds of the memory length.
282        /// 
283        /// This method ensures that the pointer is pointing to a valid position within the allocated memory block.
284        /// 
285        /// # Examples
286        /// 
287        /// ```rust
288        /// assert!(ptr.check_bounds());
289        /// ```
290        #[inline]
291        pub fn check_bounds(&self) -> bool {
292            (0..=self.memory_length).contains(&self.offset)
293        }
294
295        /// Checks if the pointer is not null and properly aligned.
296        /// 
297        /// This method ensures that the pointer is valid and meets the alignment requirements of `T`.
298        /// 
299        /// # Examples
300        /// 
301        /// ```rust
302        /// assert!(ptr.check_ptr());
303        /// ```
304        pub fn check_ptr(&self) -> bool {
305            if self.ptr.is_null() {
306                return false;
307            }
308            let align: usize = std::mem::align_of::<T>();
309            (self.ptr as usize) % align == 0
310        }
311
312        /// Returns the current offset.
313        /// 
314        /// This method provides the current offset within the memory block.
315        /// 
316        /// # Examples
317        /// 
318        /// ```rust
319        /// let offset = ptr.check_offset();
320        /// ```
321        pub fn check_offset(&self) -> usize {
322            self.offset
323        }
324
325        /// Returns the current memory length.
326        /// 
327        /// This method provides the total length of the memory block that the pointer points to.
328        /// 
329        /// # Examples
330        /// 
331        /// ```rust
332        /// let length = ptr.check_memory_length();
333        /// ```
334        pub fn check_memory_length(&self) -> usize {
335            self.memory_length
336        }
337
338        /// Changes the offset by a given byte index, if the resulting offset is within bounds.
339        /// 
340        /// This method allows you to move the pointer by a specified index within the memory block, 
341        /// ensuring that the new offset is within bounds.
342        /// 
343        /// # Examples
344        /// 
345        /// ```rust
346        /// assert!(ptr.change_offset(2).is_some());
347        /// ```
348        pub fn change_offset(&mut self, offset: isize) -> Option<()> {
349            if !self.check_ptr() {
350                return None;
351            }
352
353            let new_offset: isize = self.offset as isize + offset;
354
355            if new_offset >= 0 && new_offset < self.memory_length as isize {
356                let new_ptr: *const T = unsafe { self.ptr.byte_offset(offset) };
357                
358                self.offset = new_offset as usize;
359
360                self.ptr = new_ptr;
361                Some(())
362            } else {
363                None
364            }
365        }
366
367        /// Changes the memory length, if the new length is valid.
368        /// 
369        /// # Safety
370        /// 
371        /// This function is unsafe because it directly modifies the memory length. Ensure that the new length is 
372        /// valid and that the memory block can accommodate the new length.
373        /// 
374        /// # Examples
375        /// 
376        /// ```rust
377        /// unsafe {
378        ///     assert!(ptr.change_memory_length(10).is_some());
379        /// }
380        /// ```
381        pub unsafe fn change_memory_length(&mut self, memory_length: usize) -> Option<()> {
382            if memory_length <= 0 || self.offset >= memory_length {
383                return None;
384            }
385
386            self.memory_length = memory_length;
387            Some(())
388        }
389
390        /// Releases the pointer and returns the value it points to, if valid.
391        /// 
392        /// This method takes ownership of the pointer and returns the value it points to, ensuring that 
393        /// the pointer is valid and properly aligned.
394        /// 
395        /// # Examples
396        /// 
397        /// ```rust
398        /// let value = ptr.release_ptr().unwrap();
399        /// ```
400        pub fn release_ptr(self) -> Option<T> {
401            if self.check_ptr() {
402                unsafe {
403                    let ptr: T = *self.ptr;
404                    drop(self);
405                    Some(ptr)
406                }
407            } else {
408                None
409            }
410        }
411
412        /// Sets the pointer to null and resets the memory length and offset.
413        /// 
414        /// This method is useful for invalidating a pointer and ensuring that it no longer points to any memory.
415        /// 
416        /// # Examples
417        /// 
418        /// ```rust
419        /// ptr.set_null();
420        /// ```
421        #[inline]
422        pub fn set_null(&mut self) -> () {
423            if self.check_ptr() {
424                self.memory_length = 0;
425                self.offset = 0;
426                self.ptr = std::ptr::null();
427            }
428        }
429
430        /// Returns the memory address of the pointer as a hexadecimal string.
431        /// 
432        /// This method is useful for debugging and logging purposes to inspect the raw memory address.
433        /// 
434        /// # Examples
435        /// 
436        /// ```rust
437        /// let address = ptr.memory_address();
438        /// ```
439        #[inline]
440        pub fn memory_address(&self) -> usize {
441            self.ptr as usize
442        }
443
444        /// Converts the `ConstRawPtr` to a mutable pointer.
445        /// 
446        /// This method creates a mutable version of the `ConstRawPtr`, which allows for modification of the 
447        /// underlying data.
448        /// 
449        /// # Examples
450        /// 
451        /// ```rust
452        /// let mut_ptr = ptr.as_mut();
453        /// ```
454        #[inline]
455        pub fn as_mut(&self) -> super::mut_raw_ptr::MutRawPtr<T> {
456            super::mut_raw_ptr::MutRawPtr::new(self.ptr as *mut T, self.memory_length, self.offset)
457        }
458
459        /// Unwraps the pointer and returns the value it points to, if valid.
460        /// 
461        /// This method returns the value that the pointer points to, ensuring that the pointer is valid and 
462        /// properly aligned.
463        /// 
464        /// # Examples
465        /// 
466        /// ```rust
467        /// let value = ptr.access().unwrap();
468        /// ```
469        pub fn access(&self) -> Option<T> {
470            if self.check_ptr() {
471                Some( unsafe { *self.ptr } )
472            } else {
473                None
474            }
475        }
476
477        /// Returns a reference to the value the pointer points to, if valid.
478        /// 
479        /// This method provides a reference to the value that the pointer points to, ensuring that the pointer 
480        /// is valid and properly aligned.
481        /// 
482        /// # Examples
483        /// 
484        /// ```rust
485        /// let reference = ptr.ref_const().unwrap();
486        /// ```
487        pub fn ref_const(&self) -> Option<&T> {
488            if self.check_ptr() {
489                Some( unsafe { & *self.ptr } )
490            } else {
491                None
492            }
493        }
494
495        /// Checks if the pointer is null.
496        /// 
497        /// This method determines if the pointer is null, which is useful for validation and error checking.
498        /// 
499        /// # Examples
500        /// 
501        /// ```rust
502        /// assert!(ptr.is_null());
503        /// ```
504        #[inline]
505        pub fn is_null(&self) -> bool {
506            self.ptr.is_null()
507        }
508
509        /// Returns the size of the type `T`.
510        /// 
511        /// This method provides the size of the type `T` in bytes, which is useful for memory allocation and 
512        /// pointer arithmetic.
513        /// 
514        /// # Examples
515        /// 
516        /// ```rust
517        /// let size = ConstRawPtr::<i32>::size_of();
518        /// ```
519        #[inline]
520        pub fn size_of() -> usize {
521            std::mem::size_of::<T>()
522        }
523
524        /// Casts the pointer to a `ConstRawPtr` of another type `U`.
525        /// 
526        /// This method allows you to reinterpret the pointer as a different type, ensuring that the new type 
527        /// is compatible and properly aligned.
528        /// 
529        /// # Examples
530        /// 
531        /// ```rust
532        /// let new_ptr = ptr.cast_ptr::<f64>().unwrap();
533        /// ```
534        pub fn cast_ptr<U: Sized + Copy + Send + Sync>(&self) -> Option<ConstRawPtr<U>> {
535            if !self.ptr.is_null() {
536                Some(ConstRawPtr {
537                     ptr: self.ptr as *const U, memory_length: self.memory_length, offset: self.offset
538                })
539            } else {
540                None
541            }
542        }
543    }
544
545    impl<T: Sized + Copy + Send + Sync> Clone for ConstRawPtr<T> {
546        fn clone(&self) -> Self {
547            Self { ptr: self.ptr.clone(), memory_length: self.memory_length, offset: self.offset }
548        }
549    }
550
551    impl<T: Sized + Copy + Send + Sync> Drop for ConstRawPtr<T> {
552        fn drop(&mut self) {
553            if self.check_ptr() {
554                unsafe {
555                    let layout: std::alloc::Layout = std::alloc::Layout::new::<T>();
556                    std::alloc::dealloc(self.ptr as *mut u8, layout);
557                }
558            }
559        }
560    }
561}
562
563pub mod mut_raw_ptr {
564    use std::marker::{Copy, Send, Sync};
565    
566    /// A wrapper for `*mut T` providing methods for safely working with constant raw pointers.
567    /// 
568    /// `MutRawPtr` ensures that the raw pointer is properly aligned and provides utility methods
569    /// for checking bounds, changing offsets, and other common pointer operations. 
570    ///
571    /// Fields:
572    /// - `ptr: *mut T`: A raw constant pointer to the data.
573    /// - `memory_length: usize`: The length of the memory block in elements of T that `ptr` points to.
574    /// - `offset: usize`: The current position within the memory block.
575    ///
576    /// Notes:
577    /// - `memory_length` is not zero-based indexed.
578    /// - `offset` is zero-based indexed.
579    ///
580    /// # Safety
581    ///
582    /// Working with raw pointers is inherently unsafe. Ensure that the memory pointed to by `ptr` is valid 
583    /// and properly aligned before using this struct.
584    pub struct MutRawPtr<T> 
585    where  T: Sized + Copy + Clone + Send + Sync
586    {
587        ptr: *mut T,
588        memory_length: usize,
589        offset: usize,
590    }
591
592    impl<T: Sized + Copy + Clone + Send + Sync> MutRawPtr<T> {
593        /// Allocates memory for an array of `memory_length` elements of type `T` and returns a mutable raw pointer to the allocated memory.
594        ///
595        /// # Parameters
596        ///
597        /// - `memory_length`: The number of elements of type `T` to allocate memory for. Must be greater than 0.
598        /// - `offset`: The initial offset within the allocated memory, typically starting at 0.
599        /// - `data`: A vector of values of type `T` that will be written to the newly allocated memory. The number of elements in `data` must not exceed `memory_length`, and the vector cannot be empty.
600        ///
601        /// # Returns
602        ///
603        /// - `Some(MutRawPtr<T>)`: A mutable raw pointer to the allocated memory if the allocation is successful and the data is written correctly.
604        /// - `None`: If `memory_length` is 0 or less, or if the data vector is not within the bounds of the allocated memory (either because it is empty or has more elements than `memory_length`).
605        ///
606        /// # Panics
607        ///
608        /// This function may panic if the alignment or size parameters are invalid. Specifically, the following conditions may cause a panic:
609        /// - Alignment being zero or not a power of two.
610        /// - The size, when rounded up to the nearest multiple of alignment, overflows `isize` (i.e., the rounded value must be less than or equal to `isize::MAX`).
611        ///
612        /// # Safety
613        ///
614        /// This function is marked `unsafe` because it performs raw memory allocation. The caller is responsible for ensuring that:
615        /// - The memory is properly initialized and used correctly.
616        /// - Proper alignment and size are provided, as invalid values may cause undefined behavior.
617        /// - The `data` vector contains values that will be written to the allocated memory safely, as raw pointer operations do not include bounds checking.
618        ///
619        /// # Example
620        ///
621        /// ```rust
622        /// let alloc: *const i32 = unsafe { 
623        ///     MutRawPtr::c_malloc(vec![1, 2, 3], 5, 1).unwrap(); 
624        /// };
625        /// ```
626        pub unsafe fn c_malloc(data: Vec<T>, memory_length: usize, offset: usize) -> Option<MutRawPtr<T>> {
627            if memory_length == 0 || offset >= memory_length || data.len() == 0 || data.len() > memory_length {
628                return None;
629            }
630
631            let size: usize = std::mem::size_of::<T>() * memory_length;
632            let align: usize = std::mem::align_of::<T>();
633            let layout: std::alloc::Layout = std::alloc::Layout::from_size_align(size, align).expect("Invalid alignment or size parameters.");
634
635            unsafe {
636                let alloc: *mut T = std::alloc::alloc(layout) as *mut T;
637                
638                if alloc.is_null() {
639                    return None;
640                }
641
642                for (idx, value) in data.into_iter().enumerate() {
643                    std::ptr::write(alloc.add(idx), value);
644                }
645
646                Some(MutRawPtr::new(alloc, memory_length, offset))
647            }
648        }
649
650        /// Creates a new `MutRawPtr` with the given pointer, memory length, and offset. Make sure the length and offset are correct from C or std::alloc
651        /// 
652        /// This method ensures that the pointer is properly aligned and that the offset is within the bounds 
653        /// of the allocated memory length.
654        /// 
655        /// # Panics
656        /// 
657        /// Panics if the pointer is not aligned to `T` or if the offset is not within the bounds of the memory length.
658        /// 
659        /// # Examples
660        /// 
661        /// ```rust
662        /// let alloc_ptr: *mut i32 = ...; // Assume this is a properly allocated and aligned pointer either from C or using Rust's std::alloc::alloc and std::alloc::Layout otherwise it will panic.
663        /// let ptr = MutRawPtr::new(alloc_ptr, 1, 1);
664        /// ```
665        #[inline]
666        pub fn new(ptr: *mut T, memory_length: usize, offset: usize) -> Self {
667            assert!((ptr as usize) % std::mem::align_of::<T>() == 0, "box_raw_ptr Err: Memory Not Aligned");
668            assert!(offset < memory_length, "box_raw_ptr Err: Offset Is Not Within Bounds");
669            Self { ptr, memory_length, offset, }
670        }
671
672        /// Creates a new `MutRawPtr` with a null mutable pointer and zero memory length and offset.
673        /// 
674        /// This is useful for creating a placeholder `MutRawPtr` that can later be assigned a valid mutable pointer.
675        /// 
676        /// # Examples
677        /// 
678        /// ```rust
679        /// let null_ptr = MutRawPtr::<i32>::nullptr();
680        /// ```
681        #[inline]
682        pub fn nullptr() -> Self {
683            Self { ptr: std::ptr::null_mut(), memory_length: 0, offset: 0 }
684        }
685
686        /// Manually drops the `MutRawPtr` instance.
687        /// 
688        /// # Safety
689        /// 
690        /// This function is unsafe because it drops the instance manually, which can lead to undefined behavior 
691        /// if the instance is used after being dropped.
692        /// 
693        /// # Examples
694        /// 
695        /// ```rust
696        /// unsafe {
697        ///     mut_ptr.manual_drop();
698        /// }
699        /// ```
700        #[inline]
701        pub unsafe fn manual_drop(self) -> () {
702            drop(self);
703        }
704
705        /// Checks if the current offset is within the bounds of the memory length.
706        /// 
707        /// This method ensures that the mutable pointer is pointing to a valid position within the allocated memory block.
708        /// 
709        /// # Examples
710        /// 
711        /// ```rust
712        /// assert!(mut_ptr.check_bounds());
713        /// ```
714        #[inline]
715        pub fn check_bounds(&self) -> bool {
716            (0..=self.memory_length).contains(&self.offset)
717        }
718
719        /// Checks if the mutable pointer is not null and properly aligned.
720        /// 
721        /// This method ensures that the mutable pointer is valid and meets the alignment requirements of `T`.
722        /// 
723        /// # Examples
724        /// 
725        /// ```rust
726        /// assert!(mut_ptr.check_ptr());
727        /// ```
728        pub fn check_ptr(&self) -> bool {
729            if self.ptr.is_null() {
730                return false;
731            }
732            let align: usize = std::mem::align_of::<T>();
733            (self.ptr as usize) % align == 0
734        }
735
736        /// Returns the current offset.
737        /// 
738        /// This method provides the current offset within the memory block.
739        /// 
740        /// # Examples
741        /// 
742        /// ```rust
743        /// let offset = mut_ptr.check_offset();
744        /// ```
745        pub fn check_offset(&self) -> usize {
746            self.offset
747        }
748
749        /// Returns the current memory length.
750        /// 
751        /// This method provides the total length of the memory block that the mutable pointer points to.
752        /// 
753        /// # Examples
754        /// 
755        /// ```rust
756        /// let length = mut_ptr.check_memory_length();
757        /// ```
758        pub fn check_memory_length(&self) -> usize {
759            self.memory_length
760        }
761
762        /// Changes the offset by a given byte index, if the resulting offset is within bounds.
763        /// 
764        /// This method allows you to move the mutable pointer by a specified index within the memory block, 
765        /// ensuring that the new offset is within bounds.
766        /// 
767        /// # Examples
768        /// 
769        /// ```rust
770        /// assert!(mut_ptr.change_offset(2).is_some());
771        /// ```
772        pub fn change_offset(&mut self, offset: isize) -> Option<()> {
773            if !self.check_ptr() {
774                return None;
775            }
776
777            let new_offset: isize = self.offset as isize + offset;
778
779            if new_offset >= 0 && new_offset < self.memory_length as isize {
780                let new_ptr: *mut T = unsafe { self.ptr.byte_offset(offset) };
781                
782                self.offset = new_offset as usize;
783
784                self.ptr = new_ptr;
785                Some(())
786            } else {
787                None
788            }
789        }
790
791        /// Changes the memory length, if the new length is valid.
792        /// 
793        /// # Examples
794        /// 
795        /// ```rust
796        /// assert!(mut_ptr.change_memory_length(10).is_some());
797        /// ```
798        pub fn change_memory_length(&mut self, memory_length: usize) -> Option<()> {
799            if memory_length <= 0 || self.offset > memory_length {
800                return None;
801            }
802
803            self.memory_length = memory_length;
804            Some(())
805        }
806
807        /// Releases the mutable pointer and returns the value it points to, if valid.
808        /// 
809        /// This method takes ownership of the mutable pointer and returns the value it points to, ensuring that 
810        /// the pointer is valid and properly aligned.
811        /// 
812        /// # Examples
813        /// 
814        /// ```rust
815        /// let value = mut_ptr.release_ptr().unwrap();
816        /// ```
817        pub fn release_ptr(self) -> Option<T> {
818            if self.check_ptr() {
819                unsafe {
820                    let ptr: T = *self.ptr;
821                    drop(self);
822                    Some(ptr)
823                }
824            } else {
825                None
826            }
827        }
828
829        /// Sets the mutable pointer to null and resets the memory length and offset.
830        /// 
831        /// This method is useful for invalidating a mutable pointer and ensuring that it no longer points to any memory.
832        /// 
833        /// # Examples
834        /// 
835        /// ```rust
836        /// mut_ptr.set_null();
837        /// ```
838        #[inline]
839        pub fn set_null(&mut self) -> () {
840            if self.check_ptr() {
841                self.memory_length = 0;
842                self.offset = 0;
843                self.ptr = std::ptr::null_mut();
844            }
845        }
846
847        /// Returns the memory address of the mutable pointer as a hexadecimal string.
848        /// 
849        /// This method is useful for debugging and logging purposes to inspect the raw memory address.
850        /// 
851        /// # Examples
852        /// 
853        /// ```rust
854        /// let address = mut_ptr.memory_address();
855        /// ```
856        #[inline]
857        pub fn memory_address(&self) -> usize {
858            self.ptr as usize
859        }
860
861        /// Converts the `MutRawPtr` to a constant pointer (`ConstRawPtr`).
862        /// 
863        /// This method creates a constant version of the `MutRawPtr`, which allows for read-only access to the 
864        /// underlying data.
865        /// 
866        /// # Examples
867        /// 
868        /// ```rust
869        /// let const_ptr = mut_ptr.as_const();
870        /// ```
871        pub fn as_const(&self) -> super::const_raw_ptr::ConstRawPtr<T> {
872            super::const_raw_ptr::ConstRawPtr::new(self.ptr as *const T, self.memory_length, self.offset)
873        }
874
875        /// Unwraps the mutable pointer and returns the value it points to, if valid.
876        /// 
877        /// This method returns the value that the mutable pointer points to, ensuring that the pointer is valid and 
878        /// properly aligned.
879        /// 
880        /// # Examples
881        /// 
882        /// ```rust
883        /// let value = mut_ptr.access().unwrap();
884        /// ```
885        pub fn access(&self) -> Option<T> {
886            if self.check_ptr() {
887                Some( unsafe { *self.ptr } )
888            } else {
889                None
890            }
891        }
892
893        /// Returns a reference to the value the mutable pointer points to, if valid.
894        /// 
895        /// This method provides a reference to the value that the mutable pointer points to, ensuring that the pointer 
896        /// is valid and properly aligned.
897        /// 
898        /// # Examples
899        /// 
900        /// ```rust
901        /// let reference = mut_ptr.ref_const().unwrap();
902        /// ```
903        pub fn ref_const(&self) -> Option<&T> {
904            if self.check_ptr() {
905                Some( unsafe { & *self.ptr } )
906            } else {
907                None
908            }
909        }
910
911        /// Returns a mutable reference to the value the mutable pointer points to, if valid.
912        /// 
913        /// This method provides a mutable reference to the value that the mutable pointer points to, ensuring that 
914        /// the pointer is valid and properly aligned.
915        /// 
916        /// # Examples
917        /// 
918        /// ```rust
919        /// let mut reference = mut_ptr.ref_mut().unwrap();
920        /// *reference = 42;
921        /// ```
922        pub fn ref_mut(&self) -> Option<&mut T> {
923            if self.check_ptr() {
924                unsafe { Some(&mut *self.ptr) }
925            } else {
926                None
927            }
928        }
929
930        /// Checks if the mutable pointer is null.
931        /// 
932        /// This method determines if the mutable pointer is null, which is useful for validation and error checking.
933        /// 
934        /// # Examples
935        /// 
936        /// ```rust
937        /// assert!(mut_ptr.is_null());
938        /// ```
939        #[inline]
940        pub fn is_null(&self) -> bool {
941            self.ptr.is_null()
942        }
943
944        /// Returns the size of the type `T`.
945        /// 
946        /// This method provides the size of the type `T` in bytes, which is useful for memory allocation and 
947        /// pointer arithmetic.
948        /// 
949        /// # Examples
950        /// 
951        /// ```rust
952        /// let size = mut_ptr.size_of();
953        /// ```
954        #[inline]
955        pub fn size_of(&self) -> usize {
956            std::mem::size_of::<T>()
957        }
958
959        /// Casts the mutable pointer to a `MutRawPtr` of another type `U`.
960        /// 
961        /// This method allows you to reinterpret the mutable pointer as a different type, ensuring that the new type 
962        /// is compatible and properly aligned.
963        /// 
964        /// # Examples
965        /// 
966        /// ```rust
967        /// let new_ptr = mut_ptr.cast_ptr::<f64>().unwrap();
968        /// ```
969        pub fn cast_ptr<U: Sized + Copy + Send + Sync>(&self) -> Option<MutRawPtr<U>> {
970            if !self.ptr.is_null() {
971                Some(MutRawPtr {
972                    ptr: self.ptr as *mut U,
973                    memory_length: self.memory_length,
974                    offset: self.offset,
975                })
976            } else {
977                None
978            }
979        }
980
981        /// Writes a value into the memory location pointed to by the mutable pointer, and drops original value.
982        /// 
983        /// This method writes a value into the memory location pointed to by the mutable pointer, ensuring that 
984        /// the pointer is valid and properly aligned.
985        /// 
986        /// # Examples
987        /// 
988        /// ```rust
989        /// mut_ptr.write_ptr(42);
990        /// ```
991        pub fn write_ptr(&mut self, src: T) -> Option<()> {
992            if !self.check_ptr() {
993                return None;
994            }
995            unsafe {
996                std::ptr::write(self.ptr, src);
997            }
998            Some(())
999        }
1000    }
1001
1002    impl<T: Sized + Copy + Send + Sync> Clone for MutRawPtr<T> {
1003        fn clone(&self) -> Self {
1004            Self { ptr: self.ptr.clone(), memory_length: self.memory_length, offset: self.offset }
1005        }
1006    }
1007
1008    impl<T: Sized + Copy + Send + Sync> Drop for MutRawPtr<T> {
1009        fn drop(&mut self) {
1010            if self.check_ptr() {
1011                unsafe {
1012                    let layout: std::alloc::Layout = std::alloc::Layout::new::<T>();
1013                    std::alloc::dealloc(self.ptr as *mut u8, layout);
1014                }
1015            }
1016        }
1017    }
1018}
1019
1020#[cfg(test)]
1021mod box_raw_ptr_tests {
1022    use super::mut_raw_ptr::MutRawPtr;
1023
1024    #[test]
1025    fn c_allocator_test() -> () {
1026        /* Tests If Allocator Works */
1027        let alloc: *mut _ = unsafe { std::alloc::alloc(std::alloc::Layout::new::<i32>()) as *mut i32 };
1028        let _ = MutRawPtr::new(alloc, 1, 0);
1029    }
1030}