Skip to content

Commit

Permalink
Use [T] as the item type when appropriate.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarcho committed Mar 30, 2023
1 parent 1b167c2 commit d27208a
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 37 deletions.
40 changes: 23 additions & 17 deletions src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub unsafe trait Container<'a>: Sized {
/// The type class of this container. Used to limit which raw casts should be
type Class: AssertClassContraints<Self::Item, Self::Item>;
/// The item type held within this container.
type Item: 'a;
type Item: 'a + ?Sized + ElementSize + ElementAlign;
/// The 'raw' form of this container. Used to allow different containers to
/// share the same `CastRaw` and `TryCastRaw` impls.
type Raw: 'a + Copy;
Expand Down Expand Up @@ -206,7 +206,7 @@ unsafe impl<'a, T: 'a> Container<'a> for &'a mut T {

unsafe impl<'a, T: 'a> Container<'a> for &'a [T] {
type Class = RefT;
type Item = T;
type Item = [T];
type Raw = (*const T, usize);
type CastErr = OnlyErr;

Expand All @@ -220,7 +220,7 @@ unsafe impl<'a, T: 'a> Container<'a> for &'a [T] {

unsafe impl<'a, T: 'a> Container<'a> for &'a mut [T] {
type Class = RefT;
type Item = T;
type Item = [T];
type Raw = (*mut T, usize);
type CastErr = OnlyErr;

Expand Down Expand Up @@ -277,7 +277,7 @@ unsafe impl<'a, T: 'a> Container<'a> for NonNull<T> {
#[cfg(feature = "non_null_slice_cast")]
unsafe impl<'a, T: 'a> Container<'a> for NonNull<[T]> {
type Class = NonNullT;
type Item = T;
type Item = [T];
type Raw = (*mut T, usize);
type CastErr = OnlyErr;

Expand Down Expand Up @@ -359,7 +359,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Box<T> {
#[cfg(feature = "extern_crate_alloc")]
unsafe impl<'a, T: 'a> Container<'a> for Box<[T]> {
type Class = BoxT;
type Item = T;
type Item = [T];
type Raw = (*const T, usize);
type CastErr = ErrWithValue;

Expand Down Expand Up @@ -401,7 +401,7 @@ unsafe impl<'a, T: 'a + Copy> Container<'a> for Cow<'a, T> {
#[cfg(feature = "extern_crate_alloc")]
unsafe impl<'a, T: 'a + Copy> Container<'a> for Cow<'a, [T]> {
type Class = CowT;
type Item = T;
type Item = [T];
type Raw = RawCow<(*const T, usize), (*const T, usize, usize)>;
type CastErr = ErrWithValue;

Expand Down Expand Up @@ -437,7 +437,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Rc<T> {
#[cfg(feature = "extern_crate_alloc")]
unsafe impl<'a, T: 'a> Container<'a> for Rc<[T]> {
type Class = RcT;
type Item = T;
type Item = [T];
type Raw = (*mut T, usize);
type CastErr = ErrWithValue;

Expand Down Expand Up @@ -483,7 +483,7 @@ unsafe impl<'a, T: 'a> Container<'a> for Arc<T> {
#[cfg(feature = "extern_crate_alloc")]
unsafe impl<'a, T: 'a> Container<'a> for Arc<[T]> {
type Class = ArcT;
type Item = T;
type Item = [T];
type Raw = (*mut T, usize);
type CastErr = ErrWithValue;

Expand Down Expand Up @@ -882,39 +882,45 @@ where
}

/// Checks any constraints the container requires when casting between types.
pub trait AssertClassContraints<T, U> {
pub trait AssertClassContraints<T: ?Sized, U: ?Sized> {
const ASSERT: () = ();
}
impl<T, U> AssertClassContraints<T, U> for RefT {}
impl<T, U> AssertClassContraints<T, U> for PtrT {}
impl<T, U> AssertClassContraints<T, U> for NonNullT {}
impl<T: ?Sized, U: ?Sized> AssertClassContraints<T, U> for RefT {}
impl<T: ?Sized, U: ?Sized> AssertClassContraints<T, U> for PtrT {}
impl<T: ?Sized, U: ?Sized> AssertClassContraints<T, U> for NonNullT {}
impl<T, U> AssertClassContraints<T, U> for AtomicPtrT {}
impl<'a, C, T, U> AssertClassContraints<T, U> for OptionT<C>
impl<'a, C, T: ?Sized, U: ?Sized> AssertClassContraints<T, U> for OptionT<C>
where
C: AssertClassContraints<T, U>,
{
const ASSERT: () = C::ASSERT;
}
impl<'a, C, T, U> AssertClassContraints<T, U> for PinT<C>
impl<'a, C, T: ?Sized, U: ?Sized> AssertClassContraints<T, U> for PinT<C>
where
C: AssertClassContraints<T, U>,
{
const ASSERT: () = C::ASSERT;
}
#[cfg(feature = "extern_crate_alloc")]
impl<T, U> AssertClassContraints<T, U> for BoxT {
impl<T: ?Sized + ElementAlign, U: ?Sized + ElementAlign>
AssertClassContraints<T, U> for BoxT
{
const ASSERT: () = static_assert!(AssertSameAlign(T, U));
}
#[cfg(feature = "extern_crate_alloc")]
impl<T, U> AssertClassContraints<T, U> for RcT {
impl<T: ?Sized + ElementAlign, U: ?Sized + ElementAlign>
AssertClassContraints<T, U> for RcT
{
const ASSERT: () = static_assert!(AssertSameAlign(T, U));
}
#[cfg(feature = "extern_crate_alloc")]
impl<T, U> AssertClassContraints<T, U> for RcWeakT {
const ASSERT: () = static_assert!(AssertSameAlign(T, U));
}
#[cfg(feature = "extern_crate_alloc")]
impl<T, U> AssertClassContraints<T, U> for ArcT {
impl<T: ?Sized + ElementAlign, U: ?Sized + ElementAlign>
AssertClassContraints<T, U> for ArcT
{
const ASSERT: () = static_assert!(AssertSameAlign(T, U));
}
#[cfg(feature = "extern_crate_alloc")]
Expand Down
70 changes: 50 additions & 20 deletions src/static_assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,57 @@
use core::mem::{align_of, size_of};

pub trait AssertNonMixedZeroSize<T: Sized>: Sized {
pub trait ElementSize {
const VALUE: usize;
}
impl<T> ElementSize for T {
const VALUE: usize = size_of::<T>();
}
impl<T> ElementSize for [T] {
const VALUE: usize = size_of::<T>();
}

pub trait ElementAlign {
const VALUE: usize;
}
impl<T> ElementAlign for T {
const VALUE: usize = align_of::<T>();
}
impl<T> ElementAlign for [T] {
const VALUE: usize = align_of::<T>();
}

pub trait AssertNonMixedZeroSize<T: ?Sized + ElementSize>: ElementSize {
const ASSERT: () = {
if (size_of::<Self>() == 0) != (size_of::<T>() == 0) {
if (Self::VALUE == 0) != (T::VALUE == 0) {
panic!(
"Attempt to cast between a zero-sized type and a non-zero-sized type"
);
}
};
}
impl<T, U> AssertNonMixedZeroSize<U> for T {}
impl<T: ?Sized + ElementSize, U: ?Sized + ElementSize> AssertNonMixedZeroSize<U>
for T
{
}

pub trait AssertNonZeroSize: Sized {
pub trait AssertNonZeroSize: ElementSize {
const ASSERT: () = {
if size_of::<Self>() == 0 {
if Self::VALUE == 0 {
panic!("Attempt to cast a zero-sized type");
}
};
}
impl<T> AssertNonZeroSize for T {}
impl<T: ?Sized + ElementSize> AssertNonZeroSize for T {}

pub trait AssertSameSize<T>: Sized {
pub trait AssertSameSize<T: ?Sized + ElementSize>: ElementSize {
const ASSERT: () = {
if size_of::<Self>() == size_of::<T>() {
if Self::VALUE != T::VALUE {
panic!("Attempt to cast between two types with different sizes");
}
};
}
impl<T, U> AssertSameSize<U> for T {}
impl<T: ?Sized + ElementSize, U: ?Sized + ElementSize> AssertSameSize<U> for T {}

pub trait AssertMaxSize<T>: Sized {
const ASSERT: () = {
Expand All @@ -47,34 +70,41 @@ pub trait AssertMaxSize<T>: Sized {
}
impl<T, U> AssertMaxSize<U> for T {}

pub trait AssertSizeMultipleOf<T>: Sized {
pub trait AssertSizeMultipleOf<T: ?Sized + ElementSize>: ElementSize {
const ASSERT: () = {
if size_of::<Self>() != size_of::<T>()
&& size_of::<Self>() % size_of::<T>() != 0
{
if Self::VALUE != T::VALUE && Self::VALUE % T::VALUE != 0 {
panic!("Attempt to cast from a type which is not a multiple of the target's size");
}
};
}
impl<T, U> AssertSizeMultipleOf<U> for T {}
impl<T: ?Sized + ElementSize, U: ?Sized + ElementSize> AssertSizeMultipleOf<U>
for T
{
}

pub trait AssertSameAlign<T>: Sized {
pub trait AssertSameAlign<T: ?Sized + ElementAlign>: ElementAlign {
const ASSERT: () = {
if align_of::<Self>() == align_of::<T>() {
if Self::VALUE != T::VALUE {
panic!("Attempt to cast between two types with different alignments");
}
};
}
impl<T, U> AssertSameAlign<U> for T {}
impl<T: ?Sized + ElementAlign, U: ?Sized + ElementAlign> AssertSameAlign<U>
for T
{
}

pub trait AssertMinAlign<T>: Sized {
pub trait AssertMinAlign<T: ?Sized + ElementAlign>: ElementAlign {
const ASSERT: () = {
if align_of::<Self>() < align_of::<T>() {
if Self::VALUE < T::VALUE {
panic!("Attempt to cast to a type with a larger alignment");
}
};
}
impl<T, U> AssertMinAlign<U> for T {}
impl<T: ?Sized + ElementAlign, U: ?Sized + ElementAlign> AssertMinAlign<U>
for T
{
}

macro_rules! static_assert {
($assertion:ident($ty:ty $(, $($args:tt)*)?)) => {{
Expand Down

0 comments on commit d27208a

Please sign in to comment.