use crate::buffer::{BufferContents, BufferContentsLayout};
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
alloc::Layout,
cmp::Ordering,
fmt::{Debug, Display, Formatter, Result as FmtResult},
hash::{Hash, Hasher},
mem::{size_of, MaybeUninit},
ops::{Deref, DerefMut},
ptr::NonNull,
};
#[repr(C)]
pub struct Padded<T, const N: usize> {
value: T,
_padding: [MaybeUninit<u8>; N],
}
#[allow(non_snake_case)]
#[doc(hidden)]
#[inline(always)]
pub const fn Padded<T, const N: usize>(value: T) -> Padded<T, N> {
Padded {
value,
_padding: [MaybeUninit::uninit(); N],
}
}
impl<T, const N: usize> AsRef<T> for Padded<T, N> {
fn as_ref(&self) -> &T {
&self.value
}
}
impl<T, const N: usize> AsMut<T> for Padded<T, N> {
fn as_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl<T, const N: usize> Clone for Padded<T, N>
where
T: Clone,
{
fn clone(&self) -> Self {
Padded(self.value.clone())
}
}
impl<T, const N: usize> Copy for Padded<T, N> where T: Copy {}
impl<T, const N: usize> Debug for Padded<T, N>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.value.fmt(f)
}
}
impl<T, const N: usize> Default for Padded<T, N>
where
T: Default,
{
fn default() -> Self {
Padded(T::default())
}
}
impl<T, const N: usize> Deref for Padded<T, N> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T, const N: usize> DerefMut for Padded<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}
impl<T, const N: usize> Display for Padded<T, N>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.value.fmt(f)
}
}
impl<T, const N: usize> From<T> for Padded<T, N> {
fn from(value: T) -> Self {
Padded(value)
}
}
impl<T, const N: usize> PartialEq for Padded<T, N>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T, const N: usize> Eq for Padded<T, N> where T: Eq {}
impl<T, const N: usize> Hash for Padded<T, N>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
}
impl<T, const N: usize> PartialOrd for Padded<T, N>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl<T, const N: usize> Ord for Padded<T, N>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
unsafe impl<T, const N: usize> BufferContents for Padded<T, N>
where
T: BufferContents,
{
const LAYOUT: BufferContentsLayout =
if let Some(layout) = BufferContentsLayout::from_sized(Layout::new::<Self>()) {
layout
} else {
panic!("zero-sized types are not valid buffer contents");
};
unsafe fn ptr_from_slice(slice: NonNull<[u8]>) -> *mut Self {
debug_assert!(slice.len() == size_of::<Padded<T, N>>());
<*mut [u8]>::cast::<Padded<T, N>>(slice.as_ptr())
}
}
#[cfg(feature = "serde")]
impl<T, const N: usize> Serialize for Padded<T, N>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.value.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T, const N: usize> Deserialize<'de> for Padded<T, N>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Padded)
}
}