mod wrapper;
mod raw;
mod lazy_clone;
pub use lazy_clone::LazyClone;
pub use wrapper::AnyValueWrapper;
pub use raw::{AnyValueRaw, AnyValueSizelessRaw, AnyValueTypelessRaw};
use core::any::TypeId;
use core::{mem, ptr, slice};
use core::mem::{MaybeUninit, size_of};
pub struct Unknown;
impl Unknown {
#[inline]
pub fn is<T:'static>() -> bool {
TypeId::of::<T>() == TypeId::of::<Unknown>()
}
}
pub mod traits{
pub use super::{AnyValueSizeless, AnyValueSizelessMut};
pub use super::{AnyValueTypeless, AnyValueTypelessMut};
pub use super::{AnyValue, AnyValueMut};
pub use super::AnyValueCloneable;
}
pub trait AnyValueSizeless {
type Type: 'static ;
fn as_bytes_ptr(&self) -> *const u8;
#[inline]
unsafe fn downcast_ref_unchecked<T>(&self) -> &T{
&*(self.as_bytes_ptr() as *const T)
}
#[inline]
unsafe fn downcast_unchecked<T: 'static>(self) -> T
where Self: Sized
{
let mut tmp = MaybeUninit::<T>::uninit();
self.move_into::<T>(tmp.as_mut_ptr() as *mut u8, size_of::<T>());
tmp.assume_init()
}
#[inline]
unsafe fn move_into<KnownType:'static >(self, out: *mut u8, bytes_size: usize)
where Self: Sized
{
crate::copy_nonoverlapping_value::<KnownType>(self.as_bytes_ptr(), out, bytes_size);
mem::forget(self);
}
}
pub trait AnyValueTypeless: AnyValueSizeless {
#[inline]
fn as_bytes(&self) -> &[u8]{
unsafe{slice::from_raw_parts(
self.as_bytes_ptr(),
self.size()
)}
}
fn size(&self) -> usize;
}
pub trait AnyValue: AnyValueTypeless {
fn value_typeid(&self) -> TypeId;
#[inline]
fn downcast_ref<T: 'static>(&self) -> Option<&T>{
if self.value_typeid() != TypeId::of::<T>(){
None
} else {
Some(unsafe{ self.downcast_ref_unchecked::<T>() })
}
}
#[inline]
fn downcast<T: 'static>(self) -> Option<T>
where Self: Sized
{
if self.value_typeid() != TypeId::of::<T>(){
None
} else {
Some(unsafe{ self.downcast_unchecked::<T>() })
}
}
}
pub trait AnyValueSizelessMut: AnyValueSizeless {
fn as_bytes_mut_ptr(&mut self) -> *mut u8;
#[inline]
unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T{
&mut *(self.as_bytes_mut_ptr() as *mut T)
}
}
pub trait AnyValueTypelessMut: AnyValueTypeless + AnyValueSizelessMut {
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8]{
unsafe{slice::from_raw_parts_mut(
self.as_bytes_mut_ptr(),
self.size()
)}
}
#[inline(always)]
unsafe fn swap_unchecked<Other: AnyValueMut>(&mut self, other: &mut Other){
if !Unknown::is::<Self::Type>() {
mem::swap(
self.downcast_mut_unchecked::<Self::Type>(),
other.downcast_mut_unchecked::<Self::Type>()
);
} else if !Unknown::is::<Other::Type>() {
mem::swap(
self.downcast_mut_unchecked::<Other::Type>(),
other.downcast_mut_unchecked::<Other::Type>()
);
} else {
let bytes = self.as_bytes_mut();
ptr::swap_nonoverlapping(
bytes.as_mut_ptr(),
other.as_bytes_mut().as_mut_ptr(),
bytes.len()
);
}
}
}
pub trait AnyValueMut: AnyValueTypelessMut + AnyValue {
#[inline(always)]
fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T>{
if self.value_typeid() != TypeId::of::<T>(){
None
} else {
Some(unsafe{ self.downcast_mut_unchecked::<T>() })
}
}
#[inline(always)]
fn swap<Other: AnyValueMut>(&mut self, other: &mut Other){
assert_eq!(self.value_typeid(), other.value_typeid());
unsafe{
self.swap_unchecked(other);
}
}
}
pub trait AnyValueCloneable: AnyValueSizeless {
unsafe fn clone_into(&self, out: *mut u8);
#[inline]
fn lazy_clone(&self) -> LazyClone<'_, Self>
where Self: Sized
{
LazyClone::new(self)
}
}