use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::iter::Iterator;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
pub trait AbiClass: Sized {
unsafe fn into_unique(self) -> Self;
fn write(&mut self, val: Self);
fn size_of(&self) -> usize;
fn is_null(&self) -> bool {
self.get_obj().is_null()
}
fn as_ptr(&self) -> ClassPtr<'_, Self> {
ClassPtr::new(unsafe { self.make_ref(self.get_obj()) })
}
fn as_mut_ptr(&mut self) -> ClassMutPtr<'_, Self> {
ClassMutPtr::new(unsafe { self.make_ref(self.get_obj()) })
}
fn as_ref(&self) -> ClassRef<'_, Self> {
ClassRef::new(unsafe { self.make_ref(self.get_obj()) })
}
fn as_mut(&mut self) -> ClassRefMut<'_, Self> {
ClassRefMut::new(unsafe { self.make_ref(self.get_obj()) })
}
fn into_ref(self) -> ClassRef<'static, Self> {
ClassRef::new(self)
}
fn into_mut(self) -> ClassRefMut<'static, Self> {
ClassRefMut::new(self)
}
fn into_ptr(self) -> ClassPtr<'static, Self> {
ClassPtr::new(self)
}
fn into_mut_ptr(self) -> ClassMutPtr<'static, Self> {
ClassMutPtr::new(self)
}
fn get_raw_obj(&self) -> *const ();
unsafe fn make_ref(&self, obj: *const ()) -> Self;
fn get_obj(&self) -> *const () {
let obj = self.get_raw_obj() as usize;
let obj = obj & !(size_of::<*const ()>() - 1);
obj as *const ()
}
}
#[repr(transparent)]
pub struct Interface<T>(T);
unsafe impl<T: AbiClass + Sync> Send for Interface<T> {}
unsafe impl<T: AbiClass + Sync> Sync for Interface<T> {}
impl<T: AbiClass> Interface<T> {
pub fn new(val: T) -> Self {
Self(val)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ClassRef<'a, T: AbiClass> {
inner: T,
_mark: PhantomData<&'a T>,
}
unsafe impl<T: AbiClass + Sync> Send for ClassRef<'_, T> {}
unsafe impl<T: AbiClass + Sync> Sync for ClassRef<'_, T> {}
impl<'a, T: AbiClass> ClassRef<'a, T> {
fn new(obj: T) -> Self {
Self {
inner: obj,
_mark: PhantomData,
}
}
pub fn as_ptr(&self) -> ClassPtr<'a, T> {
ClassPtr::new(unsafe { self.inner.make_ref(self.inner.get_obj()) })
}
pub unsafe fn value_ref(&self) -> &'a T {
&*(&self.inner as *const T)
}
pub fn cast_mut(self) -> ClassRefMut<'a, T> {
ClassRefMut::<'a, T>::new(self.inner)
}
pub unsafe fn into_value(self) -> T {
self.inner
}
}
impl<T: AbiClass> Deref for ClassRef<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassRef<'_, T> {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Eq> Eq for ClassRef<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassRef<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Ord> Ord for ClassRef<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.inner, &other.inner)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ClassRefMut<'a, T: AbiClass> {
inner: T,
_mark: PhantomData<&'a T>,
}
unsafe impl<T: AbiClass + Sync> Send for ClassRefMut<'_, T> {}
unsafe impl<T: AbiClass + Sync> Sync for ClassRefMut<'_, T> {}
impl<'a, T: AbiClass> ClassRefMut<'a, T> {
fn new(obj: T) -> Self {
Self {
inner: obj,
_mark: PhantomData,
}
}
pub fn as_ptr(&self) -> ClassPtr<'a, T> {
ClassPtr::new(unsafe { self.inner.make_ref(self.inner.get_obj()) })
}
pub unsafe fn value_ref(&self) -> &'a T {
&*(&self.inner as *const T)
}
pub unsafe fn value_mut(&mut self) -> &'a mut T {
&mut *(&mut self.inner as *mut T)
}
pub fn as_mut_ptr(&self) -> ClassMutPtr<'a, T> {
ClassMutPtr::new(unsafe { self.inner.make_ref(self.inner.get_obj()) })
}
pub fn cast_const(self) -> ClassRef<'a, T> {
ClassRef::<'a, T>::new(self.inner)
}
pub unsafe fn into_value(self) -> T {
self.inner
}
}
impl<T: AbiClass> Deref for ClassRefMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: AbiClass> DerefMut for ClassRefMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassRefMut<'_, T> {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Eq> Eq for ClassRefMut<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassRefMut<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Ord> Ord for ClassRefMut<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.inner, &other.inner)
}
}
#[derive(Debug)]
pub struct ClassArray<'a, T: AbiClass> {
size: usize,
inner: T,
_mark: PhantomData<&'a T>,
}
unsafe impl<T: AbiClass + Sync> Send for ClassArray<'_, T> {}
unsafe impl<T: AbiClass + Sync> Sync for ClassArray<'_, T> {}
impl<T: AbiClass> ClassArray<'_, T> {
unsafe fn new(ptr: &T, size: usize) -> Self {
Self {
size,
inner: unsafe { ptr.make_ref(ptr.get_obj()) },
_mark: PhantomData,
}
}
}
impl<'a, T: AbiClass> ClassArray<'a, T> {
pub fn size(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0_usize
}
pub fn get(&self, pos: usize) -> Option<ClassRef<'a, T>> {
if pos >= self.size {
return None;
}
let ptr = self.inner.get_obj() as usize + self.inner.size_of() * pos;
unsafe { Some(ClassRef::new(self.inner.make_ref(ptr as *const ()))) }
}
pub fn iter(&self) -> impl Iterator<Item = ClassRef<'a, T>> + '_ {
ClassArrayIter {
array: self,
pos: 0,
}
}
pub fn rev_iter(&self) -> impl Iterator<Item = ClassRef<'a, T>> + '_ {
ClassArrayRevIter {
array: self,
pos: self.size,
}
}
}
struct ClassArrayIter<'a, T: AbiClass> {
array: *const ClassArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassArrayIter<'a, T> {
type Item = ClassRef<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &*self.array };
if self.pos < array.size {
self.pos += 1;
array.get(self.pos - 1)
} else {
None
}
}
}
struct ClassArrayRevIter<'a, T: AbiClass> {
array: *const ClassArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassArrayRevIter<'a, T> {
type Item = ClassRef<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &*self.array };
if self.pos > 0 {
self.pos -= 1;
array.get(self.pos)
} else {
None
}
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassArray<'_, T> {
fn eq(&self, other: &Self) -> bool {
for n in 0..self.size.min(other.size) {
if self.get(n) != other.get(n) {
return false;
}
}
self.size == other.size
}
}
impl<T: AbiClass + Eq> Eq for ClassArray<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassArray<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
for n in 0..self.size.min(other.size) {
let ord = PartialOrd::partial_cmp(&self.get(n), &other.get(n));
if !matches!(ord, Some(Ordering::Equal)) {
return ord;
}
}
self.size.partial_cmp(&other.size)
}
}
impl<T: AbiClass + Ord> Ord for ClassArray<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
for n in 0..self.size.min(other.size) {
let ord = Ord::cmp(&self.get(n), &other.get(n));
if ord != Ordering::Equal {
return ord;
}
}
self.size.cmp(&other.size)
}
}
#[derive(Debug)]
pub struct ClassMutArray<'a, T: AbiClass> {
size: usize,
inner: T,
_mark: PhantomData<&'a mut T>,
}
unsafe impl<T: AbiClass + Sync> Send for ClassMutArray<'_, T> {}
unsafe impl<T: AbiClass + Sync> Sync for ClassMutArray<'_, T> {}
impl<T: AbiClass> ClassMutArray<'_, T> {
unsafe fn new(ptr: &T, size: usize) -> Self {
Self {
size,
inner: unsafe { ptr.make_ref(ptr.get_obj()) },
_mark: PhantomData,
}
}
}
impl<'a, T: AbiClass> ClassMutArray<'a, T> {
pub fn size(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn get(&self, pos: usize) -> Option<ClassRef<'a, T>> {
if pos >= self.size {
return None;
}
let ptr = self.inner.get_obj() as usize + self.inner.size_of() * pos;
unsafe { Some(ClassRef::new(self.inner.make_ref(ptr as *const ()))) }
}
pub fn get_mut(&mut self, pos: usize) -> Option<ClassRefMut<'a, T>> {
if pos >= self.size {
return None;
}
let ptr = self.inner.get_obj() as usize + self.inner.size_of() * pos;
unsafe { Some(ClassRefMut::new(self.inner.make_ref(ptr as *const ()))) }
}
pub fn iter(&self) -> impl Iterator<Item = ClassRef<'a, T>> + '_ {
ClassMutArrayIter {
array: self,
pos: 0,
}
}
pub fn rev_iter(&self) -> impl Iterator<Item = ClassRef<'a, T>> + '_ {
ClassMutArrayRevIter {
array: self,
pos: self.size,
}
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = ClassRefMut<'a, T>> + '_ {
ClassMutArrayIterMut {
array: self,
pos: 0,
}
}
pub fn rev_iter_mut(&mut self) -> impl Iterator<Item = ClassRefMut<'a, T>> + '_ {
ClassMutArrayRevIterMut {
array: self,
pos: self.size,
}
}
}
struct ClassMutArrayIter<'a, T: AbiClass> {
array: *const ClassMutArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassMutArrayIter<'a, T> {
type Item = ClassRef<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &*self.array };
if self.pos < array.size {
self.pos += 1;
array.get(self.pos - 1)
} else {
None
}
}
}
struct ClassMutArrayRevIter<'a, T: AbiClass> {
array: *const ClassMutArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassMutArrayRevIter<'a, T> {
type Item = ClassRef<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &*self.array };
if self.pos > 0 {
self.pos -= 1;
array.get(self.pos)
} else {
None
}
}
}
struct ClassMutArrayIterMut<'a, T: AbiClass> {
array: *mut ClassMutArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassMutArrayIterMut<'a, T> {
type Item = ClassRefMut<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &mut *self.array };
if self.pos < array.size {
self.pos += 1;
array.get_mut(self.pos - 1)
} else {
None
}
}
}
struct ClassMutArrayRevIterMut<'a, T: AbiClass> {
array: *mut ClassMutArray<'a, T>,
pos: usize,
}
impl<'a, T: AbiClass> Iterator for ClassMutArrayRevIterMut<'a, T> {
type Item = ClassRefMut<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
let array = unsafe { &mut *self.array };
if self.pos > 0 {
self.pos -= 1;
array.get_mut(self.pos)
} else {
None
}
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassMutArray<'_, T> {
fn eq(&self, other: &Self) -> bool {
for n in 0..self.size.min(other.size) {
if self.get(n) != other.get(n) {
return false;
}
}
self.size == other.size
}
}
impl<T: AbiClass + Eq> Eq for ClassMutArray<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassMutArray<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
for n in 0..self.size.min(other.size) {
let ord = PartialOrd::partial_cmp(&self.get(n), &other.get(n));
if !matches!(ord, Some(Ordering::Equal)) {
return ord;
}
}
self.size.partial_cmp(&other.size)
}
}
impl<T: AbiClass + Ord> Ord for ClassMutArray<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
for n in 0..self.size.min(other.size) {
let ord = Ord::cmp(&self.get(n), &other.get(n));
if ord != Ordering::Equal {
return ord;
}
}
self.size.cmp(&other.size)
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct ClassPtr<'a, T: AbiClass, const N: usize = 1> {
inner: T,
_mark: PhantomData<&'a T>,
}
unsafe impl<T: AbiClass + Sync, const N: usize> Send for ClassPtr<'_, T, N> {}
unsafe impl<T: AbiClass + Sync, const N: usize> Sync for ClassPtr<'_, T, N> {}
impl<'a, T: AbiClass, const N: usize> ClassPtr<'a, T, N> {
pub fn is_null(&self) -> bool {
self.inner.is_null()
}
pub fn cast_mut(self) -> ClassMutPtr<'a, T, N> {
ClassMutPtr::<'a, T, N>::new(self.inner)
}
fn new(val: T) -> Self {
Self {
inner: val,
_mark: PhantomData,
}
}
unsafe fn unsafe_read<const M: usize>(&self) -> ClassPtr<'a, T, M> {
assert!(check_ptr::<N>(self.inner.get_raw_obj()));
assert!(!self.is_null());
assert!(M + 1 == N);
assert!(N > 1);
let pobj = self.inner.get_obj() as *const *const ();
let obj = ((pobj.read() as usize) | (M - 1)) as *const ();
ClassPtr::<'a, T, M>::new(self.inner.make_ref(obj))
}
}
impl<'a, T: AbiClass> ClassPtr<'a, T, 1> {
pub fn as_ref(&self) -> ClassRef<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
unsafe { ClassRef::new(self.inner.make_ref(self.inner.get_obj())) }
}
pub unsafe fn value_ref(&self) -> &'a T {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&*(&self.inner as *const T)
}
pub unsafe fn as_array(&self, count: usize) -> ClassArray<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
assert!(!self.inner.is_null() && count > 0);
ClassArray::new(&self.inner, count)
}
pub unsafe fn into_value(self) -> T {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
self.inner
}
}
impl<T: AbiClass> Deref for ClassPtr<'_, T, 1> {
type Target = T;
fn deref(&self) -> &Self::Target {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&self.inner
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassPtr<'_, T> {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Eq> Eq for ClassPtr<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassPtr<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Ord> Ord for ClassPtr<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.inner, &other.inner)
}
}
impl<'a, T: AbiClass> ClassPtr<'a, T, 2> {
pub unsafe fn read(&self) -> ClassPtr<'a, T, 1> {
self.unsafe_read::<1>()
}
}
impl<'a, T: AbiClass> ClassPtr<'a, T, 3> {
pub unsafe fn read(&self) -> ClassPtr<'a, T, 2> {
self.unsafe_read::<2>()
}
}
impl<'a, T: AbiClass> ClassPtr<'a, T, 4> {
pub unsafe fn read(&self) -> ClassPtr<'a, T, 3> {
self.unsafe_read::<3>()
}
}
#[cfg(target_pointer_width = "64")]
impl<'a, T: AbiClass> ClassPtr<'a, T, 5> {
pub unsafe fn read(&self) -> ClassPtr<'a, T, 4> {
self.unsafe_read::<4>()
}
}
#[cfg(target_pointer_width = "64")]
impl<'a, T: AbiClass> ClassPtr<'a, T, 6> {
pub unsafe fn read(&self) -> ClassPtr<'a, T, 5> {
self.unsafe_read::<5>()
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct ClassMutPtr<'a, T: AbiClass, const N: usize = 1> {
inner: T,
_mark: PhantomData<&'a T>,
}
unsafe impl<T: AbiClass + Sync, const N: usize> Send for ClassMutPtr<'_, T, N> {}
unsafe impl<T: AbiClass + Sync, const N: usize> Sync for ClassMutPtr<'_, T, N> {}
impl<'a, T: AbiClass, const N: usize> ClassMutPtr<'a, T, N> {
pub fn is_null(&self) -> bool {
self.inner.is_null()
}
pub fn cast_const(self) -> ClassPtr<'a, T, N> {
ClassPtr::<'a, T, N>::new(self.inner)
}
fn new(val: T) -> Self {
Self {
inner: val,
_mark: PhantomData,
}
}
unsafe fn unsafe_read<const M: usize>(&self) -> ClassMutPtr<'a, T, M> {
assert!(check_ptr::<N>(self.inner.get_raw_obj()));
assert!(!self.is_null());
assert!(M + 1 == N);
assert!(N > 1);
let pobj = self.inner.get_obj() as *const *const ();
let obj = ((pobj.read() as usize) | (M - 1)) as *const ();
unsafe { ClassMutPtr::<'a, T, M>::new(self.inner.make_ref(obj)) }
}
}
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 1> {
pub fn as_ref(&self) -> ClassRef<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
unsafe { ClassRef::new(self.inner.make_ref(self.inner.get_obj())) }
}
pub fn as_mut(&mut self) -> ClassRefMut<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
unsafe { ClassRefMut::new(self.inner.make_ref(self.inner.get_obj())) }
}
pub unsafe fn value_ref(&self) -> &'a T {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&*(&self.inner as *const T)
}
pub unsafe fn value_mut(&mut self) -> &'a mut T {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&mut *(&mut self.inner as *mut T)
}
pub unsafe fn as_array(&self, count: usize) -> ClassArray<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null() && count > 0);
ClassArray::new(&self.inner, count)
}
pub unsafe fn as_array_mut(&self, count: usize) -> ClassMutArray<'a, T> {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null() && count > 0);
ClassMutArray::new(&self.inner, count)
}
pub unsafe fn into_value(self) -> T {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
self.inner
}
}
impl<T: AbiClass> Deref for ClassMutPtr<'_, T, 1> {
type Target = T;
fn deref(&self) -> &Self::Target {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&self.inner
}
}
impl<T: AbiClass> DerefMut for ClassMutPtr<'_, T, 1> {
fn deref_mut(&mut self) -> &mut Self::Target {
assert!(check_ptr::<1>(self.inner.get_raw_obj()));
assert!(!self.inner.is_null());
&mut self.inner
}
}
impl<T: AbiClass + PartialEq> PartialEq for ClassMutPtr<'_, T> {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Eq> Eq for ClassMutPtr<'_, T> {}
impl<T: AbiClass + PartialOrd> PartialOrd for ClassMutPtr<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.inner, &other.inner)
}
}
impl<T: AbiClass + Ord> Ord for ClassMutPtr<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.inner, &other.inner)
}
}
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 2> {
pub unsafe fn read(&self) -> ClassMutPtr<'a, T, 1> {
self.unsafe_read::<1>()
}
}
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 3> {
pub unsafe fn read(&self) -> ClassMutPtr<'a, T, 2> {
self.unsafe_read::<2>()
}
}
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 4> {
pub unsafe fn read(&self) -> ClassMutPtr<'a, T, 3> {
self.unsafe_read::<3>()
}
}
#[cfg(target_pointer_width = "64")]
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 5> {
pub unsafe fn read(&self) -> ClassMutPtr<'a, T, 4> {
self.unsafe_read::<4>()
}
}
#[cfg(target_pointer_width = "64")]
impl<'a, T: AbiClass> ClassMutPtr<'a, T, 6> {
pub unsafe fn read(&self) -> ClassMutPtr<'a, T, 5> {
self.unsafe_read::<5>()
}
}
fn check_ptr<const N: usize>(obj: *const ()) -> bool {
let n = ((obj as usize) & (size_of_val(&obj) - 1)) + 1;
n == N
}