1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! 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 [TryFrom][std::convert::TryFrom]<FidlTable> implementation for
//! `ValidatedFidlTable`:
//!
//! ```
//! 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 [From][std::convert::From]<ValidatedFidlTable> implementation for `FidlTable`,
//! 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,
//! }
//! ```
//!
//! This adds a `Logical(YourErrorType)` variant to the generated error enum.
// TODO(turnage): Infer optionality based on parsing for
//                "Option<" in field types.
pub use fidl_table_validation_derive::ValidFidlTable;

pub use anyhow;

/// 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.
pub trait Validate<T> {
    type Error;
    fn validate(candidate: &T) -> std::result::Result<(), Self::Error>;
}