Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MaybeValid<T> #1833

Open
joshlf opened this issue Oct 6, 2024 · 1 comment
Open

MaybeValid<T> #1833

joshlf opened this issue Oct 6, 2024 · 1 comment

Comments

@joshlf
Copy link
Member

joshlf commented Oct 6, 2024

Needed by #497

Could be supported by #1797

A type with the same layout as T (including alignment) but fewer bit validity requirements. Bytes must be initialized if required by T, but they may be uninitialized if permitted by T. This is exactly equivalent to the semantics of the AsInitialized Ptr invariant:

zerocopy/src/pointer/ptr.rs

Lines 260 to 291 in 06fd1b2

/// The byte ranges initialized in `T` are also initialized in
/// the referent.
///
/// Formally: uninitialized bytes may only be present in
/// `Ptr<T>`'s referent where they are guaranteed to be present
/// in `T`. This is a dynamic property: if, at a particular byte
/// offset, a valid enum discriminant is set, the subsequent
/// bytes may only have uninitialized bytes as specificed by the
/// corresponding enum.
///
/// Formally, given `len = size_of_val_raw(ptr)`, at every byte
/// offset, `b`, in the range `[0, len)`:
/// - If, in any instance `t: T` of length `len`, the byte at
/// offset `b` in `t` is initialized, then the byte at offset
/// `b` within `*ptr` must be initialized.
/// - Let `c` be the contents of the byte range `[0, b)` in
/// `*ptr`. Let `S` be the subset of valid instances of `T` of
/// length `len` which contain `c` in the offset range `[0,
/// b)`. If, in any instance of `t: T` in `S`, the byte at
/// offset `b` in `t` is initialized, then the byte at offset
/// `b` in `*ptr` must be initialized.
///
/// Pragmatically, this means that if `*ptr` is guaranteed to
/// contain an enum type at a particular offset, and the enum
/// discriminant stored in `*ptr` corresponds to a valid
/// variant of that enum type, then it is guaranteed that the
/// appropriate bytes of `*ptr` are initialized as defined by
/// that variant's bit validity (although note that the
/// variant may contain another enum type, in which case the
/// same rules apply depending on the state of its
/// discriminant, and so on recursively).
AsInitialized < Initialized | Valid,

cc @kupiakos

@kupiakos
Copy link
Contributor

kupiakos commented Oct 9, 2024

Yes, essentially it acts as a deferred TryFromBytes. It also makes any external type FromBytes like MaybeUninit can, but conversion to the inner type remains unsafe.

  • MaybeValid<T>: FromBytes
  • MaybeValid<T>: IntoBytes where T: IntoBytes
  • MaybeValid<T>: DerefMut<Target = T> where T: FromBytes
  • T: TryFrom<MaybeValid<T>> where T: TryFromBytes
  • &T: TryFrom<MaybeValid<&T>> where T: TryFromBytes
  • &mut T: TryFrom<MaybeValid<&mut T>> where T: TryFromBytes
  • T: From<MaybeValid<T>> where T: FromBytes
  • &T: From<MaybeValid<&T>> where T: FromBytes
  • &mut T: From<MaybeValid<&mut T>> where T: FromBytes

Most of these conversions are unsafe on MaybeUninit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants