use std::{
fmt::{Debug, Display, Formatter},
ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, SubAssign},
};
#[derive(Debug, Copy, Clone)]
pub struct Pointer<T> {
pub ptr: *mut T,
#[cfg(feature = "bound_check")]
pub len: i64,
}
impl<T> Pointer<T> {
#[cfg(feature = "bound_check")]
pub fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.ptr, self.len as usize) }
}
pub fn cast<U>(&self) -> Pointer<U> {
#[cfg(feature = "bound_check")]
return Pointer::new(self.ptr as *mut U, self.len);
#[cfg(not(feature = "bound_check"))]
return Pointer::new(self.ptr as *mut U);
}
#[inline(always)]
pub fn get_ptr(&self) -> *mut T {
self.ptr
}
#[cfg(not(feature = "bound_check"))]
#[inline(always)]
pub fn new(ptr: *mut T) -> Self {
Self { ptr }
}
#[cfg(feature = "bound_check")]
#[inline(always)]
pub fn new(ptr: *mut T, len: i64) -> Self {
Self { ptr, len }
}
#[inline(always)]
pub fn modify(&mut self, offset: i64, value: T) {
unsafe {
self.ptr.offset(offset as isize).write(value);
}
}
#[inline(always)]
pub fn add(&mut self, offset: usize) {
unsafe {
self.ptr = self.ptr.add(offset);
}
}
#[inline(always)]
pub fn offset(&mut self, offset: i64) {
unsafe {
self.ptr = self.ptr.offset(offset as isize);
}
}
}
unsafe impl<T> Send for Pointer<T> {}
impl<T> Index<i64> for Pointer<T> {
type Output = T;
fn index(&self, index: i64) -> &Self::Output {
#[cfg(feature = "bound_check")]
{
if index < 0 || index >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &*self.ptr.offset(index as isize) }
}
}
impl<T: Display> Index<isize> for Pointer<T> {
type Output = T;
fn index(&self, index: isize) -> &Self::Output {
#[cfg(feature = "bound_check")]
{
if index < 0 || (index as i64) >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &*self.ptr.offset(index) }
}
}
impl<T: Display> Index<usize> for Pointer<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
#[cfg(feature = "bound_check")]
{
if (index as i64) >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &*self.ptr.add(index) }
}
}
impl<T: Display> IndexMut<i64> for Pointer<T> {
fn index_mut(&mut self, index: i64) -> &mut Self::Output {
#[cfg(feature = "bound_check")]
{
if index < 0 || index >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &mut *self.ptr.offset(index as isize) }
}
}
impl<T: Display> IndexMut<isize> for Pointer<T> {
fn index_mut(&mut self, index: isize) -> &mut Self::Output {
#[cfg(feature = "bound_check")]
{
if index < 0 || (index as i64) >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &mut *self.ptr.offset(index) }
}
}
impl<T: Display> IndexMut<usize> for Pointer<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
#[cfg(feature = "bound_check")]
{
if (index as i64) >= (self.len as i64) {
panic!("index out of bounds. index: {}, len: {}", index, self.len);
}
}
unsafe { &mut *self.ptr.add(index) }
}
}
impl<T> AddAssign<usize> for Pointer<T> {
fn add_assign(&mut self, rhs: usize) {
#[cfg(feature = "bound_check")]
{
self.len -= rhs as i64;
assert!(self.len >= 0);
}
unsafe {
self.ptr = self.ptr.add(rhs);
}
}
}
impl<T> Add<usize> for Pointer<T> {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
#[cfg(feature = "bound_check")]
unsafe {
Self {
ptr: self.ptr.add(rhs),
len: self.len,
}
}
#[cfg(not(feature = "bound_check"))]
unsafe {
Self {
ptr: self.ptr.add(rhs),
}
}
}
}
impl<T> AddAssign<usize> for &mut Pointer<T> {
fn add_assign(&mut self, rhs: usize) {
#[cfg(feature = "bound_check")]
{
self.len -= rhs as i64;
}
unsafe {
self.ptr = self.ptr.add(rhs);
}
}
}
impl<T> AddAssign<i64> for &mut Pointer<T> {
fn add_assign(&mut self, rhs: i64) {
#[cfg(feature = "bound_check")]
{
self.len -= rhs;
assert!(self.len >= 0);
}
unsafe {
self.ptr = self.ptr.offset(rhs as isize);
}
}
}
impl<T> Add<usize> for &mut Pointer<T> {
type Output = Pointer<T>;
fn add(self, rhs: usize) -> Self::Output {
#[cfg(feature = "bound_check")]
unsafe {
Pointer::new(self.ptr.add(rhs), self.len)
}
#[cfg(not(feature = "bound_check"))]
unsafe {
Pointer::new(self.ptr.add(rhs))
}
}
}
impl<T> AddAssign<isize> for Pointer<T> {
fn add_assign(&mut self, rhs: isize) {
#[cfg(feature = "bound_check")]
{
self.len -= rhs as i64;
assert!(self.len >= 0);
}
unsafe {
self.ptr = self.ptr.offset(rhs);
}
}
}
impl<T> Add<isize> for Pointer<T> {
type Output = Self;
fn add(self, rhs: isize) -> Self::Output {
#[cfg(feature = "bound_check")]
unsafe {
Self {
ptr: self.ptr.offset(rhs),
len: self.len,
}
}
#[cfg(not(feature = "bound_check"))]
unsafe {
Self {
ptr: self.ptr.offset(rhs),
}
}
}
}
impl<T> AddAssign<i64> for Pointer<T> {
fn add_assign(&mut self, rhs: i64) {
#[cfg(feature = "bound_check")]
{
assert!(self.len >= 0);
self.len -= rhs as i64;
}
unsafe {
self.ptr = self.ptr.offset(rhs as isize);
}
}
}
impl<T> Add<i64> for Pointer<T> {
type Output = Self;
fn add(self, rhs: i64) -> Self::Output {
#[cfg(feature = "bound_check")]
unsafe {
Self {
ptr: self.ptr.offset(rhs as isize),
len: self.len,
}
}
#[cfg(not(feature = "bound_check"))]
unsafe {
Self {
ptr: self.ptr.offset(rhs as isize),
}
}
}
}
impl<T> SubAssign<usize> for Pointer<T> {
fn sub_assign(&mut self, rhs: usize) {
#[cfg(feature = "bound_check")]
{
self.len += rhs as i64;
}
unsafe {
self.ptr = self.ptr.offset(-(rhs as isize));
}
}
}
impl<T> SubAssign<isize> for Pointer<T> {
fn sub_assign(&mut self, rhs: isize) {
#[cfg(feature = "bound_check")]
{
self.len += rhs as i64;
}
unsafe {
self.ptr = self.ptr.offset(-rhs);
}
}
}
impl<T> SubAssign<i64> for Pointer<T> {
fn sub_assign(&mut self, rhs: i64) {
#[cfg(feature = "bound_check")]
{
self.len += rhs as i64;
}
unsafe {
self.ptr = self.ptr.offset(-rhs as isize);
}
}
}
impl<T> SubAssign<i64> for &mut Pointer<T> {
fn sub_assign(&mut self, rhs: i64) {
#[cfg(feature = "bound_check")]
{
self.len += rhs as i64;
}
unsafe {
self.ptr = self.ptr.offset(-rhs as isize);
}
}
}
impl<T> Deref for Pointer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl<T> DerefMut for Pointer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.ptr }
}
}
unsafe impl<T> Sync for Pointer<T> {}
impl<T: Display> Display for Pointer<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Pointer( ptr: {}, val: {} )",
self.ptr as usize,
unsafe { self.ptr.read() }
)
}
}