A `(Try)FromBytes` `#[length]` field attribute
jswrenn opened this issue · 2 comments
See also: #5 (comment)
Addresses #1289. Discussion of alternative solutions should occur there, or in their own issues.
Many formats include a length
field in their header that describes the length of a variable-sized body; e.g., UDP:
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct Packet {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
body: [u8],
}
Such types are inconvenient to correctly parse in zerocopy; the length
must first be parsed, and only then FromBytes::try_ref_from_prefix_with_elems
can be invoked with that length
. Alternatively, the entire buffer can be parsed with try_ref_from_prefix
, and then truncated thereafter. These approaches are inconvenient.
We could potentially simplify this with a #[length]
field attribute; e.g.:
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct Packet {
src_port: [u8; 2],
dst_port: [u8; 2],
#[zerocopy::length]
length: [u8; 2],
checksum: [u8; 2],
body: [u8],
}
...such that FromBytes::ref_from_prefix
would respect the length
attribute.
Some considerations:
- This attribute should accept a function for cases in which the length in bytes must be computed
- This approach should also work on
TryFromBytes
, where excess data might be invalid - Should we attempt to support the case where the
length
is factored into a different, fixed-sized header type?
If the design in #1289 (comment) were to be implemented, this attribute could have the validator
always return ValidIfTruncatedTo(length_specified)
assuming the other fields are validated.
This should also consider:
- Whether the
length
is in bytes or number of elements, and - Whether this length includes the size of the header itself or not.