Expand description
fidl table validation tools.
This crate’s macro generates code to validate fidl tables.
Import using fidl_table_validation::*
to inherit the macro’s imports.
§Basic Example
// Some fidl table defined somewhere...
struct FidlTable {
required: Option<usize>,
optional: Option<usize>,
has_default: Option<usize>,
}
#[derive(ValidFidlTable)]
#[fidl_table_src(FidlHello)]
struct ValidatedFidlTable {
// The default is #[fidl_field_type(required)]
required: usize,
#[fidl_field_type(optional)]
optional: Option<usize>,
#[fidl_field_type(default = 22)]
has_default: usize,
}
This code generates a TryFromValidatedFidlTable
:
pub enum FidlTableValidationError {
MissingField(FidlTableMissingFieldError)
}
impl TryFrom<FidlTable> for ValidatedFidlTable {
type Error = FidlTableValidationError;
fn try_from(src: FidlTable) -> Result<ValidatedFidlTable, Self::Error> { .. }
}
and also a FromFidlTable
, so you can get a FidlTable
using validated.into()
.
§Custom Validations
When tables have logical relationships between fields that must be checked, you can use a custom validator:
struct FidlTableValidator;
impl Validate<ValidatedFidlTable> for FidlTableValidator {
type Error = String; // Can be any error type.
fn validate(candidate: &ValidatedFidlTable) -> Result<(), Self::Error> {
match candidate.required {
10 => {
Err(String::from("10 is not a valid value!"))
}
_ => Ok(())
}
}
}
#[fidl_table_src(FidlHello)]
#[fidl_table_validator(FidlTableValidator)]
struct ValidFidlTable {
...
§Non-literal defaults
Attribute syntax for name = value
only supports literals. Another
attribute for expressing defaults is used for consts. Or any type that has a
Default
impl can simply omit the literal.
const MY_DEFAULT: MyEnum = MyEnum::MyVariant;
#[derive(ValidFidlTable)]
#[fidl_table_src(FidlHello)]
struct ValidatedFidlTable {
#[fidl_field_type(default)]
has_default_impl: Vec<u32>,
#[fidl_field_with_default(MY_DEFAULT)]
has_default: MyEnum,
}
§Custom converters
Custom converters (implementing Converter
) can be used to validate the
fields. A converter
field type acts like required
(i.e. the derive
handles the optionality) and passes the unwrapped option to the given
converter. An optional_converter
field type acts like optional
and the
converter is given (and expects to generate back) Option
wrapped values.
Example:
struct RequiredConverter;
impl Converter for RequiredConverter {
type Fidl = u32;
type Validated = NonZeroU32;
type Error = anyhow::Error;
fn try_from_fidl(value: Self::Fidl) -> std::result::Result<Self::Validated, Self::Error> {
NonZeroU32::new(value).ok_or_else(|| anyhow::anyhow!("bad zero value"))
}
fn from_validated(validated: Self::Validated) -> Self::Fidl {
validated.get()
}
}
struct OptionalConverter;
enum MaybeMissing { Present(u32), Missing }
impl Converter for OptionalConverter {
type Fidl = Option<u32>;
type Validated = MaybeMissing;
type Error = std::convert::Infallible;
fn try_from_fidl(value: Self::Fidl) -> std::result::Result<Self::Validated, Self::Error> {
Ok(match value {
Some(v) => MaybeMissing::Present(v),
None => MaybeMissing::Missing,
})
}
fn from_validated(validated: Self::Validated) -> Self::Fidl {
match validated {
MaybeMissing::Present(v) => Some(v),
MaybeMissing::Missing => None,
}
}
}
#[derive(ValidFidlTable)]
#[fidl_table_src(FidlHello)]
#[fidl_table_strict]
struct ValidatedFidlTable {
#[fidl_field_type(converter = RequiredConverter)]
foo: NonZeroU32,
#[fidl_field_type(optional_converter = OptionalConverter)]
bar: MaybeMissing,
}
§Strict conversion
By default, this derive does not cause compilation errors if the source
FIDL table has more fields than the validated struct. This behavior can be
changed with the fidl_table_strict
attribute. For example, the snippet
below fails to compile if FidlHello
has more fields than the ones in
ValidatedFidlTable
.
#[derive(ValidFidlTable)]
#[fidl_table_src(FidlHello)]
#[fidl_table_strict]
struct ValidatedFidlTable {
hello: u32,
}
Fields from the FIDL table can be explicitly ignored by giving
fidl_table_strict
arguments:
#[derive(ValidFidlTable)]
#[fidl_table_src(FidlHello)]
#[fidl_table_strict(world)]
struct ValidatedFidlTable {
hello: u32,
}
This adds a Logical(YourErrorType)
variant to the generated error enum.
Re-exports§
pub use anyhow;
Traits§
- A converter trait that can convert from FIDL types
T
into a validated typeValidated
. - Validations on
T
that can be run during construction of a validated fidl table by adding the attribute#[fidl_table_validator(YourImpl)]
to the valid struct.