#![doc = include_str!("../README.md")]
#![no_std]
pub mod n_zst {
#[repr(align(1))]
pub struct ZST1;
#[repr(align(2))]
pub struct ZST2;
#[repr(align(4))]
pub struct ZST4;
#[repr(align(8))]
pub struct ZST8;
#[repr(align(16))]
pub struct ZST16;
#[repr(align(32))]
pub struct ZST32;
#[repr(align(64))]
pub struct ZST64;
#[repr(align(128))]
pub struct ZST128;
#[repr(align(256))]
pub struct ZST256;
#[repr(align(512))]
pub struct ZST512;
}
#[repr(C)]
pub struct AlignConstr<T, AlignConstrArchetype>
where
T: ?Sized,
{
_alignment_constraint: [AlignConstrArchetype; 0],
pub value: T,
}
impl<T, AlignConstrArchetype> AlignConstr<T, AlignConstrArchetype> {
pub const fn new(value: T) -> AlignConstr<T, AlignConstrArchetype> {
AlignConstr {
_alignment_constraint: [],
value,
}
}
}
impl<T, AlignConstrArchetype> core::ops::Deref for AlignConstr<T, AlignConstrArchetype>
where
T: ?Sized + core::ops::Deref,
{
type Target = <T as core::ops::Deref>::Target;
fn deref(&self) -> &Self::Target {
self.value.deref()
}
}
impl<T, AlignConstrArchetype> core::ops::DerefMut for AlignConstr<T, AlignConstrArchetype>
where
T: ?Sized + core::ops::DerefMut,
{
fn deref_mut(&mut self) -> &mut <T as core::ops::Deref>::Target {
self.value.deref_mut()
}
}
impl<T, AlignConstrArchetype> core::ops::Index<core::ops::RangeTo<usize>>
for AlignConstr<[T], AlignConstrArchetype>
where
[T]: core::ops::Index<core::ops::RangeTo<usize>, Output = [T]>,
{
type Output = <[T] as core::ops::Index<core::ops::RangeTo<usize>>>::Output;
fn index(&self, range: core::ops::RangeTo<usize>) -> &Self::Output {
unsafe { &*(&self.value[range] as *const [T] as *const Self::Output) }
}
}
#[cfg(feature = "as_slice")]
impl<T, AlignConstrArchetype> ::as_slice::AsSlice for AlignConstr<T, AlignConstrArchetype>
where
T: ::as_slice::AsSlice,
{
type Element = T::Element;
fn as_slice(&self) -> &[T::Element] {
self.value.as_slice()
}
}
#[cfg(feature = "as_slice")]
impl<T, AlignConstrArchetype> ::as_slice::AsMutSlice for AlignConstr<T, AlignConstrArchetype>
where
T: ::as_slice::AsMutSlice,
{
fn as_mut_slice(&mut self) -> &mut [T::Element] {
self.value.as_mut_slice()
}
}
impl<T, AlignConstrArchetype> Clone for AlignConstr<T, AlignConstrArchetype>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
_alignment_constraint: [],
value: self.value.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.value = source.value.clone();
}
}
impl<T, AlignConstrArchetype> Copy for AlignConstr<T, AlignConstrArchetype>
where
T: Copy,
[AlignConstrArchetype; 0]: Copy,
{
}
impl<T, AlignConstrArchetype> Default for AlignConstr<T, AlignConstrArchetype>
where
T: Default,
{
fn default() -> Self {
Self {
_alignment_constraint: [],
value: T::default(),
}
}
}
impl<T, AlignConstrArchetype> core::fmt::Debug for AlignConstr<T, AlignConstrArchetype>
where
T: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.value.fmt(f)
}
}
impl<T, AlignConstrArchetype> core::fmt::Display for AlignConstr<T, AlignConstrArchetype>
where
T: core::fmt::Display,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.value.fmt(f)
}
}
impl<T, AlignConstrArchetype> PartialEq for AlignConstr<T, AlignConstrArchetype>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T, AlignConstrArchetype> Eq for AlignConstr<T, AlignConstrArchetype>
where
T: Eq,
{
fn assert_receiver_is_total_eq(&self) {}
}
impl<T, AlignConstrArchetype> core::hash::Hash for AlignConstr<T, AlignConstrArchetype>
where
T: core::hash::Hash,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
fn hash_slice<H>(data: &[Self], state: &mut H)
where
Self: Sized,
H: core::hash::Hasher,
{
let mut i = 0;
while i < data.len() {
data[i].hash(state);
i += 1;
}
}
}
impl<T, AlignConstrArchetype> core::cmp::Ord for AlignConstr<T, AlignConstrArchetype>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.value.cmp(&other.value)
}
}
impl<T, AlignConstrArchetype> core::cmp::PartialOrd for AlignConstr<T, AlignConstrArchetype>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.value.partial_cmp(&other.value)
}
}
#[cfg(test)]
mod tests {
use crate::{
n_zst::{ZST1, ZST128, ZST16, ZST2, ZST256, ZST32, ZST4, ZST512, ZST64, ZST8},
AlignConstr,
};
#[test]
fn size_of_align_constr_t_geq_size_of_t() {
use core::mem::size_of;
assert!(size_of::<AlignConstr::<u8, u16>>() >= size_of::<u8>());
}
#[test]
const fn align_of_u8_le_align_of_zst512() {
use core::mem::align_of;
assert!(align_of::<u8>() < align_of::<ZST512>());
}
#[test]
const fn check_alignments_of_n_zsts() {
use core::mem::align_of;
assert!(align_of::<ZST1>() == 1);
assert!(align_of::<ZST2>() == 2);
assert!(align_of::<ZST4>() == 4);
assert!(align_of::<ZST8>() == 8);
assert!(align_of::<ZST16>() == 16);
assert!(align_of::<ZST32>() == 32);
assert!(align_of::<ZST64>() == 64);
assert!(align_of::<ZST128>() == 128);
assert!(align_of::<ZST256>() == 256);
assert!(align_of::<ZST512>() == 512);
}
#[test]
const fn align_constr_allows_overaligning() {
use core::mem::align_of;
assert!(align_of::<AlignConstr::<u8, ZST512>>() > align_of::<u8>());
}
#[test]
const fn align_constr_doesnt_reduce_alignment() {
use core::mem::align_of;
assert!(align_of::<AlignConstr::<ZST512, u8>>() == align_of::<ZST512>());
}
}