use core::fmt;
use core::hash::Hash;
use core::marker::PhantomData;
use crate::mem::MaybeUninit;
use crate::pointer::{DefaultSize, Size, Slice};
use crate::ZeroCopy;
#[derive(ZeroCopy)]
#[repr(C)]
#[zero_copy(crate)]
pub struct Ref<T, O: Size = DefaultSize> {
offset: O,
#[zero_copy(ignore)]
_marker: PhantomData<T>,
}
impl<T, O: Size> Ref<T, O> {
pub(crate) fn new_raw(offset: usize) -> Self {
let Some(offset) = O::from_usize(offset) else {
panic!("Ref offset {offset} not in the legal range of 0-{}", O::MAX);
};
Self {
offset,
_marker: PhantomData,
}
}
#[inline]
pub fn offset(&self) -> usize {
self.offset.as_usize()
}
}
impl<T, const N: usize, O: Size> Ref<[T; N], O>
where
T: ZeroCopy,
{
pub fn into_slice(self) -> Slice<T, O> {
Slice::new_with_offset(self.offset, N)
}
}
impl<T, O: Size> Ref<MaybeUninit<T>, O> {
#[inline]
pub const fn assume_init(self) -> Ref<T, O> {
Ref {
offset: self.offset,
_marker: PhantomData,
}
}
}
impl<T, O: Size> Ref<T, O>
where
T: ZeroCopy,
{
pub const fn zero() -> Self {
Self {
offset: O::ZERO,
_marker: PhantomData,
}
}
pub fn new(offset: usize) -> Self {
Self::new_raw(offset)
}
}
impl<T, O: Size> fmt::Debug for Ref<T, O>
where
O: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Ref<{}> {{ offset: {:?} }}",
core::any::type_name::<T>(),
self.offset
)
}
}
impl<T, O: Size> Clone for Ref<T, O> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T, O: Size> Copy for Ref<T, O> {}
impl<T, O: Size> PartialEq for Ref<T, O>
where
O: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.offset == other.offset
}
}
impl<T, O: Size> Eq for Ref<T, O> where O: Eq {}
impl<T, O: Size> PartialOrd for Ref<T, O>
where
O: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.offset.partial_cmp(&other.offset)
}
}
impl<T, O: Size> Ord for Ref<T, O>
where
O: Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.offset.cmp(&other.offset)
}
}
impl<T, O: Size> Hash for Ref<T, O>
where
O: Hash,
{
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.offset.hash(state);
}
}