Skip to main content

fidl_next_codec/
validate.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use thiserror::Error;
6
7use crate::Slot;
8
9/// Errors that can be produced when validating FIDL messages.
10///
11/// Validation errors may occur during both encoding and decoding.
12#[derive(Error, Debug, PartialEq, Eq, Clone)]
13pub enum ValidationError {
14    /// Vector too long.
15    #[error("vector too long, has {count}, limit is {limit}")]
16    VectorTooLong {
17        /// The number of elements.
18        count: u64,
19        /// The maximum number of elements allowed.
20        limit: u64,
21    },
22    /// String too long.
23    #[error("string too long, has {count}, limit is {limit}")]
24    StringTooLong {
25        /// The number of bytes in the string.
26        count: u64,
27        /// The maximum number of bytes allowed.
28        limit: u64,
29    },
30}
31
32/// Implemented by types that have constraints that can be validated.
33pub trait Constrained {
34    /// Type of constraint information for this type.
35    type Constraint: Copy;
36
37    /// Validate a slot of this type against a constraint. Can be called when
38    /// pointers/envelopes are just presence markers.
39    fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError>;
40}
41
42// Arrays have the constraints of their member.
43impl<T: Constrained, const N: usize> Constrained for [T; N] {
44    type Constraint = T::Constraint;
45    fn validate(
46        mut slot: Slot<'_, Self>,
47        constraint: Self::Constraint,
48    ) -> Result<(), ValidationError> {
49        // SAFETY: this slot must be initialized.
50        let slice = unsafe { (slot.as_mut_ptr() as *mut [T]).as_mut() }.unwrap();
51        for member in slice {
52            // SAFETY: every member of the array must have been initialized already.
53            let member_slot = unsafe { Slot::new_unchecked(member) };
54            T::validate(member_slot, constraint)?;
55        }
56        Ok(())
57    }
58}