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}