Skip to main content

fidl_next_codec/
wire_type.rs

1// Copyright 2026 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 core::mem::MaybeUninit;
6
7use crate::Constrained;
8
9/// A FIDL wire type.
10///
11/// # Safety
12///
13/// ## Lifetime erasure
14///
15/// Wire types allow for lifetime erasure and restoration. A type that
16/// implements `Wire` may have an instance of its [`Narrowed`][Wire::Narrowed]
17/// type erased by transmuting to an instance of itself.
18///
19/// It is only safe to expose values and mutable reference to the narrowed
20/// versions of wire types. While type erased, it is only safe to expose shared
21/// references to the implementing type (i.e. `&'de Foo<'static>`).
22///
23/// ## Padding
24///
25/// `zero_padding` must write zeroes to (at least) the padding bytes of `out`.
26pub unsafe trait Wire: 'static + Sized + Constrained {
27    /// The narrowed wire type, restricted to the `'de` lifetime.
28    type Narrowed<'de>: Constrained<Constraint = Self::Constraint>;
29
30    /// Writes zeroes to the padding for this type, if any.
31    fn zero_padding(out: &mut MaybeUninit<Self>);
32}
33
34// SAFETY: Slices of `Wire` types are also valid `Wire` types because elements are laid out
35// sequentially with no padding between them, and lifetime erasure is safe if it is safe for `T`.
36unsafe impl<T: Wire, const N: usize> Wire for [T; N] {
37    type Narrowed<'de> = [T::Narrowed<'de>; N];
38
39    #[inline]
40    fn zero_padding(out: &mut MaybeUninit<Self>) {
41        for i in 0..N {
42            // SAFETY: `i` is in bounds for the array of size `N`, and the cast to `MaybeUninit<T>`
43            // is valid because `MaybeUninit<T>` has the same layout as `T`.
44            let out_i = unsafe { &mut *out.as_mut_ptr().cast::<MaybeUninit<T>>().add(i) };
45            T::zero_padding(out_i);
46        }
47    }
48}