Skip to content

Commit a1595a7

Browse files
committed
[WIP] TryFromBytes
TODO: - Should we require `FromBytes: FromZeroes + TryFromBytes` or `FromZeroes: TryFromBytes`? We obviously only need one of these, but which one? Makes progress on #5
1 parent 514cc58 commit a1595a7

File tree

2 files changed

+619
-116
lines changed

2 files changed

+619
-116
lines changed

src/derive_util.rs

+45
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,48 @@ macro_rules! union_has_padding {
6262
false $(|| core::mem::size_of::<$t>() != core::mem::size_of::<$ts>())*
6363
};
6464
}
65+
66+
#[doc(hidden)]
67+
pub use project::project as __project;
68+
69+
/// Implements `TryFromBytes` for a struct type by delegating to existing
70+
/// implementations for each of its fields.
71+
///
72+
/// # Safety
73+
///
74+
/// `$ty` must be a struct type, `$f` must list every field's name, and `$f_ty`
75+
/// must be the correct types for those fields.
76+
#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
77+
#[macro_export]
78+
macro_rules! impl_try_from_bytes_for_struct {
79+
($ty:ty { $($f:tt: $f_ty:ty),* } $(=> $validation_method:ident)?) => {
80+
// SAFETY: The caller promises that all fields are listed with their
81+
// correct types. We validate that every field is valid, which is the
82+
// only requirement for the entire struct to be valid. Thus, we
83+
// correctly implement `is_bit_valid` as required by the trait's safety
84+
// documentation.
85+
#[allow(unused_qualifications)]
86+
unsafe impl zerocopy::TryFromBytes for $ty {
87+
fn is_bit_valid(bytes: &zerocopy::MaybeValid<Self>) -> bool {
88+
true $(&& {
89+
let f: &zerocopy::MaybeValid<$f_ty>
90+
= zerocopy::derive_util::__project!(&bytes.$f);
91+
zerocopy::TryFromBytes::is_bit_valid(f)
92+
})*
93+
$(&& {
94+
// SAFETY: We just validated that all of the struct's fields
95+
// are valid, which means that the struct itself is valid.
96+
// That is the only precondition of `assume_valid_ref`.
97+
let slf = unsafe { bytes.assume_valid_ref() };
98+
// TODO: What about interior mutability? One approach would
99+
// be to have the validation method operate on a
100+
// `#[repr(transparent)]` `Freeze` container that implements
101+
// `Projectable`. If we eventually get a `Freeze` or
102+
// `NoCell` trait, that container could implement `Deref`
103+
// for types which don't contain any cells.
104+
slf.$validation_method()
105+
})?
106+
}
107+
}
108+
}
109+
}

0 commit comments

Comments
 (0)