google / google/zerocopy

Support custom validators for `TryFromBytes`

Open
#1,330 4 comments 5 reactions 0 assignees View on GitHub
customer-request
Dominant language
Rust
Stars
2.6k
Forks
179
Avg merge
1d 19h
Merged PRs (30d)
29

Description

These are kinds of validity that users may need to have checked before transmutation from `&[u8]` to `&T`:

1. The language-level validity of the bits for the type of each field in `T`, e.g. a `bool` must be either `0` or `1`. This is implemented by the `derive`.
1. The library-level validity of the bits in `T`, e.g. an invariant that the first field is less than the second. This can be referenced by the `derive` but inherently must be user-controlled.
1. The library-level validity of the individual fields in `T`, based on the above library-level check applied to each field. This is also implemented by the `derive`.
1. The library-level validity of the length of the struct given the header contents, e.g. the `length` field is equal to the size of the tail slice. This only applies to dynamically sized structs ending in a slice.

The plan discussed in #5 and #372 is to support the concept of a _custom validator_, a function or closure provided to `derive(TryFromBytes)` that will always be called before allowing a `TryFromBytes` transmute to succeed.

### Open Questions

- Should users be able to provide their own error type, to communicate the way in which the validation failed? How would this be exposed to the higher-level `TryFromBytes` APIs?
- How will data validation interact with custom DSTs? Is the validator also responsible for validating the correct length of the tail slice, or even deriving the correct length (as proposed in https://github.com/google/zerocopy/issues/1289#issuecomment-2121244709)?
- What happens if the user provides both a [`#[length]`](https://github.com/google/zerocopy/issues/1328) and custom validator function and they disagree?
- Given `struct Outer { x: u8, y: Inner }`/`struct Inner { a: [u8; 4], b: [u8] }`, is the validator for `Outer` allowed to communicate a maximum length for the tail slice located inside of `Inner`? What if `Inner` has a custom validator that returns "valid if the tail slice is truncated to N", but `Outer` has a different return from its custom validator?
- What are the required signature(s) for the custom validators? In theory the derive can support many return types simultaneously, including `bool`, `Result<(), CustomError>`, or `Result, CustomError>` (to communicate a required length).
- When zerocopy's expectations surrounding validator behavior are violated, should it panic (terrible for embedded), only panic in debug mode (middle ground a la `+` overflow checking), or always reject the input (could miss bugs in validators).
- Should we ban mutation inside of a validator (either programmatically or as a safety invariant)? See also: #1831

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.