Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions zerocopy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,14 @@ pub const REPR_C_UNION_VARIANT_ID: i128 = -3;
#[doc(hidden)]
#[derive(Copy, Clone, Debug)]
pub enum TryFromBytesDerive {}
#[doc(hidden)]
#[derive(Copy, Clone, Debug)]
pub enum ProjectDerive {}

#[cfg(any(feature = "derive", test))]
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
#[doc(hidden)]
pub use zerocopy_derive::Project;

/// # Safety
///
Expand Down Expand Up @@ -1212,9 +1220,9 @@ pub unsafe trait HasTag<Client = TryFromBytesDerive> {

/// Projects a given field from `Self`.
///
/// All implementations of `HasField` for a particular field `f` in `Self`
/// should use the same `Field` type; this ensures that `Field` is inferable
/// given an explicit `VARIANT_ID` and `FIELD_ID`.
/// All implementations of `HasField` for a particular `Client` and field `f`
/// in `Self` should use the same `Field` type; this ensures that `Field` is
/// inferable given an explicit `Client`, `VARIANT_ID`, and `FIELD_ID`.
///
/// The `Client` parameter exists solely to disambiguate between implementations
/// of `HasField` that would otherwise conflict.
Expand All @@ -1224,12 +1232,14 @@ pub unsafe trait HasTag<Client = TryFromBytesDerive> {
/// A field `f` is `HasField` for `Self` if and only if:
///
/// - If `Self` has the layout of a struct or union type, then `VARIANT_ID` is
/// `STRUCT_VARIANT_ID` or `UNION_VARIANT_ID` respectively; otherwise, if
/// `Self` has the layout of an enum type, `VARIANT_ID` is the numerical index
/// of the enum variant in which `f` appears. Note that `Self` does not need
/// to actually *be* such a type – it just needs to have the same layout as
/// such a type. For example, a `#[repr(transparent)]` wrapper around an enum
/// has the same layout as that enum.
/// `STRUCT_VARIANT_ID` or `UNION_VARIANT_ID` respectively. For internal
/// projections of `repr(C)` unions, `VARIANT_ID` may instead be
/// `REPR_C_UNION_VARIANT_ID`. Otherwise, if `Self` has the layout of an enum
/// type and `f` appears in a variant named `v`, `VARIANT_ID` is
/// `zerocopy::ident_id!(v)`. Note that `Self` does not need to actually *be*
/// such a type – it just needs to have the same layout as such a type. For
/// example, a `#[repr(transparent)]` wrapper around an enum has the same
/// layout as that enum.
/// - If `f` has name `n`, `FIELD_ID` is `zerocopy::ident_id!(n)`; otherwise,
/// if `f` is at index `i`, `FIELD_ID` is `zerocopy::ident_id!(i)`.
/// - `Field` is a type with the same visibility as `f`.
Expand Down Expand Up @@ -1274,7 +1284,8 @@ pub unsafe trait HasField<Client, Field, const VARIANT_ID: i128, const FIELD_ID:
/// `Self::Invariants` comes out.
///
/// The `Client` parameter exists solely to disambiguate between implementations
/// of `HasField` that would otherwise conflict.
/// of `ProjectField` (and their corresponding `HasField` implementations) that
/// would otherwise conflict.
///
/// # Safety
///
Expand Down Expand Up @@ -1338,7 +1349,9 @@ where
// referent. This default implementation of `is_projectable`
// is non-destructive, as it does not overwrite any part of
// the referent.
crate::STRUCT_VARIANT_ID | crate::UNION_VARIANT_ID => true,
crate::STRUCT_VARIANT_ID
| crate::UNION_VARIANT_ID
| crate::REPR_C_UNION_VARIANT_ID => true,
_enum_variant => {
use crate::invariant::{Validity, ValidityKind};
match I::Validity::KIND {
Expand Down
14 changes: 7 additions & 7 deletions zerocopy/src/wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,13 @@ unsafe impl<T: HasTag<Client> + ?Sized, Client> HasTag<Client> for ReadOnly<T> {

// SAFETY: `ReadOnly<T>` is a `#[repr(transparent)]` wrapper around `T`, and so
// has the same fields at the same offsets. Thus, it satisfies the safety
// invariants of `HasField<Client, Field, VARIANT_ID, FIELD_ID>` for field `f` exactly
// when `T` does, as guaranteed by the `T: HasField` bound:
// - If `VARIANT_ID` is `STRUCT_VARIANT_ID` or `UNION_VARIANT_ID`, then `T` has
// the layout of a struct or union type. Since `ReadOnly<T>` is a transparent
// wrapper around `T`, it does too. Otherwise, if `VARIANT_ID` is an enum
// variant index, then `T` has the layout of an enum type, and `ReadOnly<T>`
// does too.
// invariants of `HasField<Client, Field, VARIANT_ID, FIELD_ID>` for field `f`
// exactly when `T` does, as guaranteed by the `T: HasField` bound:
// - If `VARIANT_ID` is `STRUCT_VARIANT_ID`, `UNION_VARIANT_ID`, or
// `REPR_C_UNION_VARIANT_ID`, then `T` has the layout of the corresponding
// struct or union type. Since `ReadOnly<T>` is a transparent wrapper around
// `T`, it does too. Otherwise, `VARIANT_ID` is the identifier ID of an enum
// variant; `T` has the layout of an enum type, and `ReadOnly<T>` does too.
// - By `T: HasField<_, _, _, FIELD_ID>`:
// - `T` has a field `f` with name `n` such that
// `FIELD_ID = zerocopy::ident_id!(n)` or at index `i` such that
Expand Down
1 change: 1 addition & 0 deletions zerocopy/zerocopy-derive/src/derive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod from_bytes;
pub mod into_bytes;
pub mod known_layout;
pub mod project;
pub mod try_from_bytes;
pub mod unaligned;

Expand Down
Loading
Loading