// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
//
// Copyright 2022 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
//! Utilities used by macros and by `zerocopy-derive`.
//!
//! These are defined here `zerocopy` rather than in code generated by macros or
//! by `zerocopy-derive` so that they can be compiled once rather than
//! recompiled for every invocation (e.g., if they were defined in generated
//! code, then deriving `IntoBytes` and `FromBytes` on three different types
//! would result in the code in question being emitted and compiled six
//! different times).
#![allow(missing_debug_implementations)]
// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
// this `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[cfg(not(target_pointer_width = "16"))]
use core::ptr::{self, NonNull};
use core::{marker::PhantomData, mem, num::Wrapping};
use crate::{
pointer::{
cast::CastSized,
invariant::{Aligned, Initialized, Valid},
BecauseImmutable,
},
FromBytes, Immutable, IntoBytes, KnownLayout, Ptr, ReadOnly, TryFromBytes, ValidityError,
};
/// Projects the type of the field at `Index` in `Self` without regard for field
/// privacy.
///
/// The `Index` parameter is any sort of handle that identifies the field; its
/// definition is the obligation of the implementer.
///
/// # Safety
///
/// Unsafe code may assume that this accurately reflects the definition of
/// `Self`.
pub unsafe trait Field<Index> {
/// The type of the field at `Index`.
type Type: ?Sized;
}
#[cfg_attr(
not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
diagnostic::on_unimplemented(
message = "`{T}` has {PADDING_BYTES} total byte(s) of padding",
label = "types with padding cannot implement `IntoBytes`",
note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields",
note = "consider adding explicit fields where padding would be",
note = "consider using `#[repr(packed)]` to remove padding"
)
)]
pub trait PaddingFree<T: ?Sized, const PADDING_BYTES: usize> {}
impl<T: ?Sized> PaddingFree<T, 0> for () {}
// FIXME(#1112): In the slice DST case, we should delegate to *both*
// `PaddingFree` *and* `DynamicPaddingFree` (and probably rename `PaddingFree`
// to `StaticPaddingFree` or something - or introduce a third trait with that
// name) so that we can have more clear error messages.
#[cfg_attr(
not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
diagnostic::on_unimplemented(
message = "`{T}` has one or more padding bytes",
label = "types with padding cannot implement `IntoBytes`",
note = "consider using `zerocopy::Unalign` to lower the alignment of individual fields",
note = "consider adding explicit fields where padding would be",
note = "consider using `#[repr(packed)]` to remove padding"
)
)]
pub trait DynamicPaddingFree<T: ?Sized, const HAS_PADDING: bool> {}
impl<T: ?Sized> DynamicPaddingFree<T, false> for () {}
#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[cfg(not(target_pointer_width = "16"))]
const _64K: usize = 1 << 16;
// FIXME(#29), FIXME(https://github.com/rust-lang/rust/issues/69835): Remove
// this `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[cfg(not(target_pointer_width = "16"))]