use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::{any, fmt};
use crate::endian::{Big, ByteOrder, Little, Native};
use crate::ZeroCopy;
#[derive(ZeroCopy)]
#[zero_copy(crate, swap_bytes_self, bounds = {T: ZeroCopy})]
#[repr(transparent)]
pub struct Endian<T, E>
where
E: ByteOrder,
{
value: T,
#[zero_copy(ignore)]
_marker: PhantomData<E>,
}
impl<T> Endian<T, Little>
where
T: ZeroCopy,
{
#[inline]
pub fn le(value: T) -> Self {
Self::new(value)
}
}
impl<T> Endian<T, Big>
where
T: ZeroCopy,
{
#[inline]
pub fn be(value: T) -> Self {
Self::new(value)
}
}
impl<T, E> Endian<T, E>
where
T: ZeroCopy,
E: ByteOrder,
{
#[inline]
#[track_caller]
pub fn new(value: T) -> Self {
const {
assert!(T::CAN_SWAP_BYTES, "Type does not support byte-swapping");
}
Self {
value: T::swap_bytes::<E>(value),
_marker: PhantomData,
}
}
#[inline]
#[track_caller]
pub fn to_ne(self) -> T {
const {
assert!(T::CAN_SWAP_BYTES, "Type does not support byte-swapping");
}
T::swap_bytes::<E>(self.value)
}
#[inline]
pub fn to_raw(self) -> T {
self.value
}
}
impl<T, E> fmt::Debug for Endian<T, E>
where
T: ZeroCopy + fmt::Debug,
E: ByteOrder,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Endian<{}>({:?})", any::type_name::<E>(), self.value)
}
}
impl<T, E> Clone for Endian<T, E>
where
T: ZeroCopy + Clone,
E: ByteOrder,
{
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
_marker: self._marker,
}
}
}
impl<T, E> Copy for Endian<T, E>
where
T: ZeroCopy + Copy,
E: ByteOrder,
{
}
impl<T> Deref for Endian<T, Native> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T> DerefMut for Endian<T, Native> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}