fidl/
encoding.rs

1// Copyright 2018 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
5//! FIDL encoding and decoding.
6
7// TODO(https://fxbug.dev/42069912): This file is too big. Split it into smaller files.
8
9pub use static_assertions::const_assert_eq;
10
11use crate::endpoints::ProtocolMarker;
12use crate::handle::{
13    Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, ObjectType, Rights, Status,
14};
15use crate::time::{Instant, Ticks, Timeline};
16use crate::{Error, MethodType, Result};
17use bitflags::bitflags;
18use std::cell::RefCell;
19use std::marker::PhantomData;
20use std::{mem, ptr, str};
21
22////////////////////////////////////////////////////////////////////////////////
23// Traits
24////////////////////////////////////////////////////////////////////////////////
25
26/// Trait for a "Box" that wraps a handle when it's inside a client. Useful when
27/// we need some infrastructure to make our underlying channels work the way the
28/// client code expects.
29pub trait ProxyChannelBox<D: ResourceDialect>: std::fmt::Debug + Send + Sync {
30    /// Receives a message on the channel and registers this `Channel` as
31    /// needing a read on receiving a `io::std::ErrorKind::WouldBlock`.
32    #[allow(clippy::type_complexity)]
33    fn recv_etc_from(
34        &self,
35        ctx: &mut std::task::Context<'_>,
36        buf: &mut D::MessageBufEtc,
37    ) -> std::task::Poll<Result<(), Option<<D::ProxyChannel as ProxyChannelFor<D>>::Error>>>;
38
39    #[cfg(not(target_os = "fuchsia"))]
40    /// Closed reason for proxies.
41    fn closed_reason(&self) -> Option<String> {
42        None
43    }
44
45    /// Get a reference to the boxed channel.
46    fn as_channel(&self) -> &D::ProxyChannel;
47
48    /// Write data to a Proxy channel
49    fn write_etc(
50        &self,
51        bytes: &[u8],
52        handles: &mut [<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition],
53    ) -> Result<(), Option<<D::ProxyChannel as ProxyChannelFor<D>>::Error>>;
54
55    /// Return whether a `ProxyChannel` is closed.
56    fn is_closed(&self) -> bool;
57
58    /// Unbox this channel
59    fn unbox(self) -> D::ProxyChannel;
60}
61
62/// Message buffer used to hold a message in a particular dialect.
63pub trait MessageBufFor<D: ResourceDialect>: std::fmt::Debug + Send + Sync {
64    /// Create a new message buffer.
65    fn new() -> Self;
66
67    /// Discard any allocated-but-unused space in the byte portion of this buffer.
68    fn shrink_bytes_to_fit(&mut self) {}
69
70    /// Access the contents of this buffer as two vectors.
71    fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>);
72}
73
74/// Channel used for proxies in a particular dialect.
75pub trait ProxyChannelFor<D: ResourceDialect>:
76    std::fmt::Debug + crate::epitaph::ChannelLike
77{
78    /// Box we put around a `ProxyChannel` when using it within a client.
79    type Boxed: ProxyChannelBox<D>;
80
81    /// Type of the errors we get from this proxy channel.
82    type Error: Into<crate::TransportError>;
83
84    /// Handle disposition used in this dialect.
85    ///
86    /// This is for sending handles, and includes the intended type/rights.
87    type HandleDisposition: HandleDispositionFor<D>;
88
89    /// Construct a new box around a proxy channel.
90    fn boxed(self) -> Self::Boxed;
91
92    /// Write data to a Proxy channel
93    fn write_etc(
94        &self,
95        bytes: &[u8],
96        handles: &mut [Self::HandleDisposition],
97    ) -> Result<(), Option<Self::Error>>;
98}
99
100/// Handle disposition struct used for a particular dialect.
101pub trait HandleDispositionFor<D: ResourceDialect>: std::fmt::Debug {
102    /// Wrap a handle in a handle disposition.
103    fn from_handle(
104        handle: D::Handle,
105        object_type: crate::ObjectType,
106        rights: crate::Rights,
107    ) -> Self;
108}
109
110/// Handle type used for a particular dialect.
111pub trait HandleFor<D: ResourceDialect> {
112    /// Handle info used in this dialect.
113    ///
114    /// This is used for receiving handles, and includes type/rights from the
115    /// kernel.
116    type HandleInfo: HandleInfoFor<D>;
117
118    /// Produce an invalid version of `Handle` used as a place filler when
119    /// we remove handles from an array.
120    fn invalid() -> Self;
121
122    /// Check whether a handle is invalid.
123    fn is_invalid(&self) -> bool;
124}
125
126/// Handle info struct used for a particular dialect.
127pub trait HandleInfoFor<D: ResourceDialect>: std::fmt::Debug {
128    /// Verifies a `HandleInfo` has the type and rights we expect and
129    /// extracts the `D::Handle` from it.
130    fn consume(
131        &mut self,
132        expected_object_type: crate::ObjectType,
133        expected_rights: crate::Rights,
134    ) -> Result<D::Handle>;
135
136    /// Destroy the given handle info, leaving it invalid.
137    fn drop_in_place(&mut self);
138}
139
140/// Describes how a given transport encodes resources like handles.
141pub trait ResourceDialect: 'static + Sized + Default + std::fmt::Debug + Copy + Clone {
142    /// Handle type used in this dialect.
143    type Handle: HandleFor<Self>;
144
145    /// Message buffer type used in this dialect.
146    type MessageBufEtc: MessageBufFor<Self>;
147
148    /// Channel type used for proxies in this dialect.
149    type ProxyChannel: ProxyChannelFor<Self>;
150
151    /// Get a thread-local common instance of `TlsBuf`
152    fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R;
153}
154
155/// Indicates a type is encodable as a handle in a given resource dialect.
156pub trait EncodableAsHandle: Into<<Self::Dialect as ResourceDialect>::Handle> {
157    /// What resource dialect can encode this object as a handle.
158    type Dialect: ResourceDialect<Handle: Into<Self>>;
159}
160
161/// A FIDL type marker.
162///
163/// This trait is only used for compile time dispatch. For example, we can
164/// parameterize code on `T: TypeMarker`, but we would never write `value: T`.
165/// In fact, `T` is often a zero-sized struct. From the user's perspective,
166/// `T::Owned` is the FIDL type's "Rust type". For example, for the FIDL type
167/// `string:10`, `T` is `BoundedString<10>` and `T::Owned` is `String`.
168///
169/// For primitive types and user-defined types, `Self` is actually the same as
170/// `Self::Owned`. For all others (strings, arrays, vectors, handles, endpoints,
171/// optionals, error results), `Self` is a zero-sized struct that uses generics
172/// to represent FIDL type information such as the element type or constraints.
173///
174/// # Safety
175///
176/// * Implementations of `encode_is_copy` must only return true if it is safe to
177///   transmute from `*const Self::Owned` to `*const u8` and read `inline_size`
178///   bytes starting from that address.
179///
180/// * Implementations of `decode_is_copy` must only return true if it is safe to
181///   transmute from `*mut Self::Owned` to `*mut u8` and write `inline_size`
182///   bytes starting at that address.
183pub unsafe trait TypeMarker: 'static + Sized {
184    /// The owned Rust type which this FIDL type decodes into.
185    type Owned;
186
187    /// Returns the minimum required alignment of the inline portion of the
188    /// encoded object. It must be a (nonzero) power of two.
189    fn inline_align(context: Context) -> usize;
190
191    /// Returns the size of the inline portion of the encoded object, including
192    /// padding for alignment. Must be a multiple of `inline_align`.
193    fn inline_size(context: Context) -> usize;
194
195    /// Returns true if the memory layout of `Self::Owned` matches the FIDL wire
196    /// format and encoding requires no validation. When true, we can optimize
197    /// encoding arrays and vectors of `Self::Owned` to a single memcpy.
198    ///
199    /// This can be true even when `decode_is_copy` is false. For example, bools
200    /// require validation when decoding, but they do not require validation
201    /// when encoding because Rust guarantees a bool is either 0x00 or 0x01.
202    #[inline(always)]
203    fn encode_is_copy() -> bool {
204        false
205    }
206
207    /// Returns true if the memory layout of `Self::Owned` matches the FIDL wire
208    /// format and decoding requires no validation. When true, we can optimize
209    /// decoding arrays and vectors of `Self::Owned` to a single memcpy.
210    #[inline(always)]
211    fn decode_is_copy() -> bool {
212        false
213    }
214}
215
216/// A FIDL value type marker.
217///
218/// Value types are guaranteed to never contain handles. As a result, they can
219/// be encoded by immutable reference (or by value for `Copy` types).
220pub trait ValueTypeMarker: TypeMarker {
221    /// The Rust type to use for encoding. This is a particular `Encode<Self>`
222    /// type cheaply obtainable from `&Self::Owned`. There are three cases:
223    ///
224    /// - Special cases such as `&[T]` for vectors.
225    /// - For primitives, bits, and enums, it is `Owned`.
226    /// - Otherwise, it is `&Owned`.
227    type Borrowed<'a>;
228
229    /// Cheaply converts from `&Self::Owned` to `Self::Borrowed`.
230    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_>;
231}
232
233/// A FIDL resource type marker.
234///
235/// Resource types are allowed to contain handles. As a result, they must be
236/// encoded by mutable reference so that handles can be zeroed out.
237pub trait ResourceTypeMarker: TypeMarker {
238    /// The Rust type to use for encoding. This is a particular `Encode<Self>`
239    /// type cheaply obtainable from `&mut Self::Owned`. There are three cases:
240    ///
241    /// - Special cases such as `&mut [T]` for vectors.
242    /// - When `Owned: HandleBased`, it is `Owned`.
243    /// - Otherwise, it is `&mut Owned`.
244    type Borrowed<'a>;
245
246    /// Cheaply converts from `&mut Self::Owned` to `Self::Borrowed`. For
247    /// `HandleBased` types this is "take" (it returns an owned handle and
248    /// replaces `value` with `Handle::invalid`), and for all other types it is
249    /// "borrow" (just converts from one reference to another).
250    fn take_or_borrow(value: &mut Self::Owned) -> Self::Borrowed<'_>;
251}
252
253/// A Rust type that can be encoded as the FIDL type `T`.
254///
255/// # Safety
256///
257/// Implementations of `encode` must write every byte in
258/// `encoder.buf[offset..offset + T::inline_size(encoder.context)]` unless
259/// returning an `Err` value.
260pub unsafe trait Encode<T: TypeMarker, D: ResourceDialect>: Sized {
261    /// Encodes the object into the encoder's buffers. Any handles stored in the
262    /// object are swapped for `Handle::INVALID`.
263    ///
264    /// Implementations that encode out-of-line objects must call `depth.increment()?`.
265    ///
266    /// # Safety
267    ///
268    /// Callers must ensure `offset` is a multiple of `T::inline_align` and
269    /// `encoder.buf` has room for writing `T::inline_size` bytes at `offset`.
270    unsafe fn encode(self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth)
271        -> Result<()>;
272}
273
274/// A Rust type that can be decoded from the FIDL type `T`.
275pub trait Decode<T: TypeMarker, D>: 'static + Sized {
276    /// Creates a valid instance of `Self`. The specific value does not matter,
277    /// since it will be overwritten by `decode`.
278    // TODO(https://fxbug.dev/42069855): Take context parameter to discourage using this.
279    fn new_empty() -> Self;
280
281    /// Decodes an object of type `T` from the decoder's buffers into `self`.
282    ///
283    /// Implementations must validate every byte in
284    /// `decoder.buf[offset..offset + T::inline_size(decoder.context)]` unless
285    /// returning an `Err` value. Implementations that decode out-of-line
286    /// objects must call `depth.increment()?`.
287    ///
288    /// # Safety
289    ///
290    /// Callers must ensure `offset` is a multiple of `T::inline_align` and
291    /// `decoder.buf` has room for reading `T::inline_size` bytes at `offset`.
292    unsafe fn decode(
293        &mut self,
294        decoder: &mut Decoder<'_, D>,
295        offset: usize,
296        depth: Depth,
297    ) -> Result<()>
298    where
299        D: ResourceDialect;
300}
301
302////////////////////////////////////////////////////////////////////////////////
303// Resource Dialects
304////////////////////////////////////////////////////////////////////////////////
305
306/// Box around an async channel. Needed to implement `ResourceDialect` for
307/// `DefaultFuchsiaResourceDialect` but not so useful for that case.
308#[derive(Debug)]
309pub struct FuchsiaProxyBox(crate::AsyncChannel);
310
311impl FuchsiaProxyBox {
312    /// Future that returns when the channel is closed.
313    pub fn on_closed(&self) -> crate::OnSignalsRef<'_> {
314        self.0.on_closed()
315    }
316
317    /// See [`crate::AsyncChannel::read_etc`]
318    pub fn read_etc(
319        &self,
320        cx: &mut std::task::Context<'_>,
321        bytes: &mut Vec<u8>,
322        handles: &mut Vec<crate::HandleInfo>,
323    ) -> std::task::Poll<Result<(), crate::Status>> {
324        self.0.read_etc(cx, bytes, handles)
325    }
326
327    /// Signal peer
328    pub fn signal_peer(
329        &self,
330        clear: crate::Signals,
331        set: crate::Signals,
332    ) -> Result<(), zx_status::Status> {
333        use crate::Peered;
334        self.0.as_ref().signal_peer(clear, set)
335    }
336}
337
338impl ProxyChannelBox<DefaultFuchsiaResourceDialect> for FuchsiaProxyBox {
339    fn write_etc(
340        &self,
341        bytes: &[u8],
342        handles: &mut [HandleDisposition<'static>],
343    ) -> Result<(), Option<zx_status::Status>> {
344        self.0
345            .write_etc(bytes, handles)
346            .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
347    }
348
349    fn recv_etc_from(
350        &self,
351        ctx: &mut std::task::Context<'_>,
352        buf: &mut crate::MessageBufEtc,
353    ) -> std::task::Poll<Result<(), Option<zx_status::Status>>> {
354        self.0
355            .recv_etc_from(ctx, buf)
356            .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
357    }
358
359    fn is_closed(&self) -> bool {
360        self.0.is_closed()
361    }
362
363    #[cfg(not(target_os = "fuchsia"))]
364    fn closed_reason(&self) -> Option<String> {
365        self.0.closed_reason()
366    }
367
368    fn unbox(self) -> <DefaultFuchsiaResourceDialect as ResourceDialect>::ProxyChannel {
369        self.0
370    }
371
372    fn as_channel(&self) -> &<DefaultFuchsiaResourceDialect as ResourceDialect>::ProxyChannel {
373        &self.0
374    }
375}
376
377/// The default [`ResourceDialect`]. Encodes everything into a channel
378/// MessageBuf for sending via channels between Fuchsia services.
379#[derive(Debug, Default, Copy, Clone)]
380pub struct DefaultFuchsiaResourceDialect;
381impl ResourceDialect for DefaultFuchsiaResourceDialect {
382    type Handle = Handle;
383    type MessageBufEtc = crate::MessageBufEtc;
384    type ProxyChannel = crate::AsyncChannel;
385
386    #[inline]
387    fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R {
388        thread_local!(static TLS_BUF: RefCell<TlsBuf<DefaultFuchsiaResourceDialect>> =
389            RefCell::new(TlsBuf::default()));
390        TLS_BUF.with(|buf| f(&mut buf.borrow_mut()))
391    }
392}
393
394impl MessageBufFor<DefaultFuchsiaResourceDialect> for crate::MessageBufEtc {
395    fn new() -> crate::MessageBufEtc {
396        let mut ret = crate::MessageBufEtc::new();
397        ret.ensure_capacity_bytes(MIN_BUF_BYTES_SIZE);
398        ret
399    }
400
401    fn shrink_bytes_to_fit(&mut self) {
402        self.shrink_bytes_to_fit();
403    }
404
405    fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<HandleInfo>) {
406        self.split_mut()
407    }
408}
409
410impl ProxyChannelFor<DefaultFuchsiaResourceDialect> for crate::AsyncChannel {
411    type Boxed = FuchsiaProxyBox;
412    type Error = zx_status::Status;
413    type HandleDisposition = HandleDisposition<'static>;
414
415    fn boxed(self) -> FuchsiaProxyBox {
416        FuchsiaProxyBox(self)
417    }
418
419    fn write_etc(
420        &self,
421        bytes: &[u8],
422        handles: &mut [HandleDisposition<'static>],
423    ) -> Result<(), Option<zx_status::Status>> {
424        self.write_etc(bytes, handles)
425            .map_err(|x| Some(x).filter(|x| *x != zx_status::Status::PEER_CLOSED))
426    }
427}
428
429impl HandleDispositionFor<DefaultFuchsiaResourceDialect> for HandleDisposition<'static> {
430    fn from_handle(handle: Handle, object_type: ObjectType, rights: Rights) -> Self {
431        HandleDisposition::new(HandleOp::Move(handle), object_type, rights, Status::OK)
432    }
433}
434
435impl HandleFor<DefaultFuchsiaResourceDialect> for Handle {
436    type HandleInfo = HandleInfo;
437
438    fn invalid() -> Self {
439        Handle::invalid()
440    }
441
442    fn is_invalid(&self) -> bool {
443        Handle::is_invalid(self)
444    }
445}
446
447impl HandleInfoFor<DefaultFuchsiaResourceDialect> for HandleInfo {
448    fn consume(
449        &mut self,
450        expected_object_type: ObjectType,
451        expected_rights: Rights,
452    ) -> Result<Handle> {
453        let handle_info = std::mem::replace(
454            self,
455            HandleInfo::new(Handle::invalid(), ObjectType::NONE, Rights::NONE),
456        );
457        let received_object_type = handle_info.object_type;
458        if expected_object_type != ObjectType::NONE
459            && received_object_type != ObjectType::NONE
460            && expected_object_type != received_object_type
461        {
462            return Err(Error::IncorrectHandleSubtype {
463                expected: expected_object_type,
464                received: received_object_type,
465            });
466        }
467
468        let received_rights = handle_info.rights;
469        if expected_rights != Rights::SAME_RIGHTS
470            && received_rights != Rights::SAME_RIGHTS
471            && expected_rights != received_rights
472        {
473            if !received_rights.contains(expected_rights) {
474                return Err(Error::MissingExpectedHandleRights {
475                    missing_rights: expected_rights - received_rights,
476                });
477            }
478            return match handle_info.handle.replace(expected_rights) {
479                Ok(r) => Ok(r),
480                Err(status) => Err(Error::HandleReplace(status)),
481            };
482        }
483        Ok(handle_info.handle)
484    }
485
486    #[inline(always)]
487    fn drop_in_place(&mut self) {
488        *self = HandleInfo::new(Handle::invalid(), ObjectType::NONE, Rights::NONE);
489    }
490}
491
492/// A never type for handles in `NoHandleResourceDialect`.
493#[cfg(not(target_os = "fuchsia"))]
494#[derive(Debug)]
495pub enum NoHandles {}
496
497#[cfg(not(target_os = "fuchsia"))]
498impl ProxyChannelBox<NoHandleResourceDialect> for NoHandles {
499    fn recv_etc_from(
500        &self,
501        _ctx: &mut std::task::Context<'_>,
502        _buf: &mut <NoHandleResourceDialect as ResourceDialect>::MessageBufEtc,
503    ) -> std::task::Poll<Result<(), Option<zx_status::Status>>> {
504        unreachable!()
505    }
506
507    fn write_etc(
508        &self,
509        _bytes: &[u8],
510        _handles: &mut [
511            <<NoHandleResourceDialect as ResourceDialect>::ProxyChannel
512            as ProxyChannelFor<NoHandleResourceDialect>>::HandleDisposition],
513    ) -> Result<(), Option<zx_status::Status>> {
514        unreachable!()
515    }
516
517    fn is_closed(&self) -> bool {
518        unreachable!()
519    }
520
521    fn unbox(self) -> <NoHandleResourceDialect as ResourceDialect>::ProxyChannel {
522        unreachable!()
523    }
524
525    fn as_channel(&self) -> &<NoHandleResourceDialect as ResourceDialect>::ProxyChannel {
526        unreachable!()
527    }
528}
529
530/// A resource dialect which doesn't support handles at all.
531#[cfg(not(target_os = "fuchsia"))]
532#[derive(Debug, Default, Copy, Clone)]
533pub struct NoHandleResourceDialect;
534
535#[cfg(not(target_os = "fuchsia"))]
536impl ResourceDialect for NoHandleResourceDialect {
537    type Handle = NoHandles;
538    type MessageBufEtc = NoHandles;
539    type ProxyChannel = NoHandles;
540
541    #[inline]
542    fn with_tls_buf<R>(f: impl FnOnce(&mut TlsBuf<Self>) -> R) -> R {
543        thread_local!(static TLS_BUF: RefCell<TlsBuf<NoHandleResourceDialect>> =
544            RefCell::new(TlsBuf::default()));
545        TLS_BUF.with(|buf| f(&mut buf.borrow_mut()))
546    }
547}
548
549#[cfg(not(target_os = "fuchsia"))]
550impl MessageBufFor<NoHandleResourceDialect> for NoHandles {
551    fn new() -> Self {
552        unreachable!()
553    }
554
555    fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<NoHandles>) {
556        unreachable!()
557    }
558}
559
560#[cfg(not(target_os = "fuchsia"))]
561impl ProxyChannelFor<NoHandleResourceDialect> for NoHandles {
562    type Boxed = NoHandles;
563    type Error = zx_status::Status;
564    type HandleDisposition = NoHandles;
565
566    fn boxed(self) -> NoHandles {
567        unreachable!()
568    }
569
570    fn write_etc(
571        &self,
572        _bytes: &[u8],
573        _handles: &mut [NoHandles],
574    ) -> Result<(), Option<zx_status::Status>> {
575        unreachable!()
576    }
577}
578
579#[cfg(not(target_os = "fuchsia"))]
580impl crate::epitaph::ChannelLike for NoHandles {
581    fn write_epitaph(&self, _bytes: &[u8]) -> std::result::Result<(), crate::TransportError> {
582        unreachable!()
583    }
584}
585
586#[cfg(not(target_os = "fuchsia"))]
587impl HandleFor<NoHandleResourceDialect> for NoHandles {
588    type HandleInfo = NoHandles;
589
590    fn invalid() -> Self {
591        unreachable!()
592    }
593
594    fn is_invalid(&self) -> bool {
595        unreachable!()
596    }
597}
598
599#[cfg(not(target_os = "fuchsia"))]
600impl HandleDispositionFor<NoHandleResourceDialect> for NoHandles {
601    fn from_handle(
602        _handle: <NoHandleResourceDialect as ResourceDialect>::Handle,
603        _object_type: crate::ObjectType,
604        _rights: crate::Rights,
605    ) -> Self {
606        unreachable!()
607    }
608}
609
610#[cfg(not(target_os = "fuchsia"))]
611impl HandleInfoFor<NoHandleResourceDialect> for NoHandles {
612    fn consume(
613        &mut self,
614        _expected_object_type: crate::ObjectType,
615        _expected_rights: crate::Rights,
616    ) -> Result<<NoHandleResourceDialect as ResourceDialect>::Handle> {
617        unreachable!()
618    }
619
620    fn drop_in_place(&mut self) {
621        unreachable!()
622    }
623}
624
625/// A resource dialect which doesn't support handles at all.
626#[cfg(target_os = "fuchsia")]
627pub type NoHandleResourceDialect = DefaultFuchsiaResourceDialect;
628
629////////////////////////////////////////////////////////////////////////////////
630// Constants
631////////////////////////////////////////////////////////////////////////////////
632
633/// The maximum recursion depth of encoding and decoding. Each pointer to an
634/// out-of-line object counts as one step in the recursion depth.
635pub const MAX_RECURSION: usize = 32;
636
637/// The maximum number of handles allowed in a FIDL message.
638///
639/// Note that this number is one less for large messages for the time being. See
640/// (https://fxbug.dev/42068341) for progress, or to report problems caused by
641/// this specific limitation.
642pub const MAX_HANDLES: usize = 64;
643
644/// Indicates that an optional value is present.
645pub const ALLOC_PRESENT_U64: u64 = u64::MAX;
646/// Indicates that an optional value is present.
647pub const ALLOC_PRESENT_U32: u32 = u32::MAX;
648/// Indicates that an optional value is absent.
649pub const ALLOC_ABSENT_U64: u64 = 0;
650/// Indicates that an optional value is absent.
651pub const ALLOC_ABSENT_U32: u32 = 0;
652
653/// Special ordinal signifying an epitaph message.
654pub const EPITAPH_ORDINAL: u64 = 0xffffffffffffffffu64;
655
656/// The current wire format magic number
657pub const MAGIC_NUMBER_INITIAL: u8 = 1;
658
659////////////////////////////////////////////////////////////////////////////////
660// Helper functions
661////////////////////////////////////////////////////////////////////////////////
662
663/// Rounds `x` up if necessary so that it is a multiple of `align`.
664///
665/// Requires `align` to be a (nonzero) power of two.
666#[doc(hidden)] // only exported for use in macros or generated code
667#[inline(always)]
668pub fn round_up_to_align(x: usize, align: usize) -> usize {
669    debug_assert_ne!(align, 0);
670    debug_assert_eq!(align & (align - 1), 0);
671    // https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding
672    (x + align - 1) & !(align - 1)
673}
674
675/// Resize a vector without zeroing added bytes.
676///
677/// The type `T` must be `Copy`. This is not enforced in the type signature
678/// because it is used in generic contexts where verifying this requires looking
679/// at control flow. See `decode_vector` for an example.
680///
681/// # Safety
682///
683/// This is unsafe when `new_len > old_len` because it leaves new elements at
684/// indices `old_len..new_len` uninitialized. The caller must overwrite all the
685/// new elements before reading them. "Reading" includes any operation that
686/// extends the vector, such as `push`, because this could reallocate the vector
687/// and copy the uninitialized bytes.
688///
689/// FIDL conformance tests are used to validate that there are no uninitialized
690/// bytes in the output across a range of types and values.
691// TODO(https://fxbug.dev/42075223): Fix safety issues, use MaybeUninit.
692#[inline]
693unsafe fn resize_vec_no_zeroing<T>(buf: &mut Vec<T>, new_len: usize) {
694    if new_len > buf.capacity() {
695        buf.reserve(new_len - buf.len());
696    }
697    // Safety:
698    // - `new_len` must be less than or equal to `capacity()`:
699    //   The if-statement above guarantees this.
700    // - The elements at `old_len..new_len` must be initialized:
701    //   They are purposely left uninitialized, making this function unsafe.
702    buf.set_len(new_len);
703}
704
705/// Helper type for checking encoding/decoding recursion depth.
706#[doc(hidden)] // only exported for use in macros or generated code
707#[derive(Debug, Copy, Clone)]
708#[repr(transparent)]
709pub struct Depth(usize);
710
711impl Depth {
712    /// Increments the depth, and returns an error if it exceeds the limit.
713    #[inline(always)]
714    pub fn increment(&mut self) -> Result<()> {
715        self.0 += 1;
716        if self.0 > MAX_RECURSION {
717            return Err(Error::MaxRecursionDepth);
718        }
719        Ok(())
720    }
721}
722
723////////////////////////////////////////////////////////////////////////////////
724// Helper macros
725////////////////////////////////////////////////////////////////////////////////
726
727/// Given `T: TypeMarker`, expands to a `T::Owned::new_empty` call.
728#[doc(hidden)] // only exported for use in macros or generated code
729#[macro_export]
730macro_rules! new_empty {
731    ($ty:ty) => {
732        <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, _>>::new_empty()
733    };
734    ($ty:ty, $d:path) => {
735        <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, $d>>::new_empty()
736    };
737}
738
739/// Given `T: TypeMarker`, expands to a `T::Owned::decode` call.
740#[doc(hidden)] // only exported for use in macros or generated code
741#[macro_export]
742macro_rules! decode {
743    ($ty:ty, $out_value:expr, $decoder:expr, $offset:expr, $depth:expr) => {
744        <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, _>>::decode(
745            $out_value, $decoder, $offset, $depth,
746        )
747    };
748    ($ty:ty, $d:path, $out_value:expr, $decoder:expr, $offset:expr, $depth:expr) => {
749        <<$ty as $crate::encoding::TypeMarker>::Owned as $crate::encoding::Decode<$ty, $d>>::decode(
750            $out_value, $decoder, $offset, $depth,
751        )
752    };
753}
754
755////////////////////////////////////////////////////////////////////////////////
756// Wire format
757////////////////////////////////////////////////////////////////////////////////
758
759/// Wire format version to use during encode / decode.
760#[derive(Clone, Copy, Debug)]
761pub enum WireFormatVersion {
762    /// FIDL 2023 wire format.
763    V2,
764}
765
766/// Context for encoding and decoding.
767///
768/// WARNING: Do not construct this directly unless you know what you're doing.
769/// FIDL uses `Context` to coordinate soft migrations, so improper uses of it
770/// could result in ABI breakage.
771#[derive(Clone, Copy, Debug)]
772pub struct Context {
773    /// Wire format version to use when encoding / decoding.
774    pub wire_format_version: WireFormatVersion,
775}
776
777// We only support one wire format right now, so context should be zero size.
778const_assert_eq!(mem::size_of::<Context>(), 0);
779
780impl Context {
781    /// Returns the header flags to set when encoding with this context.
782    #[inline]
783    pub(crate) fn at_rest_flags(&self) -> AtRestFlags {
784        match self.wire_format_version {
785            WireFormatVersion::V2 => AtRestFlags::USE_V2_WIRE_FORMAT,
786        }
787    }
788}
789
790////////////////////////////////////////////////////////////////////////////////
791// Encoder
792////////////////////////////////////////////////////////////////////////////////
793
794/// Encoding state
795#[derive(Debug)]
796pub struct Encoder<'a, D: ResourceDialect> {
797    /// Encoding context.
798    pub context: Context,
799
800    /// Buffer to write output data into.
801    pub buf: &'a mut Vec<u8>,
802
803    /// Buffer to write output handles into.
804    handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
805
806    /// Phantom data for `D`, which is here to provide types not values.
807    _dialect: PhantomData<D>,
808}
809
810/// The default context for encoding.
811#[inline]
812fn default_encode_context() -> Context {
813    Context { wire_format_version: WireFormatVersion::V2 }
814}
815
816impl<'a, D: ResourceDialect> Encoder<'a, D> {
817    /// FIDL-encodes `x` into the provided data and handle buffers.
818    #[inline]
819    pub fn encode<T: TypeMarker>(
820        buf: &'a mut Vec<u8>,
821        handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
822        x: impl Encode<T, D>,
823    ) -> Result<()> {
824        let context = default_encode_context();
825        Self::encode_with_context::<T>(context, buf, handles, x)
826    }
827
828    /// FIDL-encodes `x` into the provided data and handle buffers, using the
829    /// specified encoding context.
830    ///
831    /// WARNING: Do not call this directly unless you know what you're doing.
832    /// FIDL uses `Context` to coordinate soft migrations, so improper uses of
833    /// this function could result in ABI breakage.
834    #[inline]
835    pub fn encode_with_context<T: TypeMarker>(
836        context: Context,
837        buf: &'a mut Vec<u8>,
838        handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
839        x: impl Encode<T, D>,
840    ) -> Result<()> {
841        fn prepare_for_encoding<'a, D: ResourceDialect>(
842            context: Context,
843            buf: &'a mut Vec<u8>,
844            handles: &'a mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
845            ty_inline_size: usize,
846        ) -> Encoder<'a, D> {
847            // An empty response can have size zero.
848            // This if statement is needed to not break the padding write below.
849            if ty_inline_size != 0 {
850                let aligned_inline_size = round_up_to_align(ty_inline_size, 8);
851                // Safety: The uninitialized elements are written by `x.encode`,
852                // except for the trailing padding which is zeroed below.
853                unsafe {
854                    resize_vec_no_zeroing(buf, aligned_inline_size);
855
856                    // Zero the last 8 bytes in the block to ensure padding bytes are zero.
857                    let padding_ptr = buf.get_unchecked_mut(aligned_inline_size - 8) as *mut u8;
858                    (padding_ptr as *mut u64).write_unaligned(0);
859                }
860            }
861            handles.truncate(0);
862            Encoder { buf, handles, context, _dialect: PhantomData }
863        }
864        let mut encoder = prepare_for_encoding(context, buf, handles, T::inline_size(context));
865        // Safety: We reserve `T::inline_size` bytes in `encoder.buf` above.
866        unsafe { x.encode(&mut encoder, 0, Depth(0)) }
867    }
868
869    /// In debug mode only, asserts that there is enough room in the buffer to
870    /// write an object of type `T` at `offset`.
871    #[inline(always)]
872    pub fn debug_check_bounds<T: TypeMarker>(&self, offset: usize) {
873        debug_assert!(offset + T::inline_size(self.context) <= self.buf.len());
874    }
875
876    /// Encodes a primitive numeric type.
877    ///
878    /// # Safety
879    ///
880    /// The caller must ensure that `self.buf` has room for writing
881    /// `T::inline_size` bytes as `offset`.
882    #[inline(always)]
883    pub unsafe fn write_num<T: numeric::Numeric>(&mut self, num: T, offset: usize) {
884        debug_assert!(offset + mem::size_of::<T>() <= self.buf.len());
885        // Safety: The caller ensures `offset` is valid for writing
886        // sizeof(T) bytes. Transmuting to a same-or-wider
887        // integer or float pointer is safe because we use `write_unaligned`.
888        let ptr = self.buf.get_unchecked_mut(offset) as *mut u8;
889        (ptr as *mut T).write_unaligned(num);
890    }
891
892    /// Writes the given handle to the handles list.
893    #[inline(always)]
894    pub fn push_next_handle(
895        &mut self,
896        handle: <D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition,
897    ) {
898        self.handles.push(handle)
899    }
900
901    /// Returns an offset for writing `len` out-of-line bytes. Zeroes padding
902    /// bytes at the end if `len` is not a multiple of 8.
903    ///
904    /// # Safety
905    ///
906    /// The caller must ensure that `len` is nonzero.
907    #[inline]
908    pub unsafe fn out_of_line_offset(&mut self, len: usize) -> usize {
909        debug_assert!(len > 0);
910        let new_offset = self.buf.len();
911        let padded_len = round_up_to_align(len, 8);
912        debug_assert!(padded_len >= 8);
913        let new_len = self.buf.len() + padded_len;
914        resize_vec_no_zeroing(self.buf, new_len);
915        // Zero the last 8 bytes in the block to ensure padding bytes are zero.
916        // It's more efficient to always write 8 bytes regardless of how much
917        // padding is needed because we will overwrite non-padding afterwards.
918        let padding_ptr = self.buf.get_unchecked_mut(new_len - 8) as *mut u8;
919        (padding_ptr as *mut u64).write_unaligned(0);
920        new_offset
921    }
922
923    /// Write padding at the specified offset.
924    ///
925    /// # Safety
926    ///
927    /// The caller must ensure that `self.buf` has room for writing `len` bytes
928    /// as `offset`.
929    #[inline(always)]
930    pub unsafe fn padding(&mut self, offset: usize, len: usize) {
931        if len == 0 {
932            return;
933        }
934        debug_assert!(offset + len <= self.buf.len());
935        // Safety:
936        // - The caller ensures `offset` is valid for writing `len` bytes.
937        // - All u8 pointers are properly aligned.
938        ptr::write_bytes(self.buf.as_mut_ptr().add(offset), 0, len);
939    }
940}
941
942unsafe impl<T: Timeline + 'static, U: 'static> TypeMarker for Instant<T, U> {
943    type Owned = Self;
944
945    #[inline(always)]
946    fn inline_align(_context: Context) -> usize {
947        mem::align_of::<Self>()
948    }
949
950    #[inline(always)]
951    fn inline_size(_context: Context) -> usize {
952        mem::size_of::<Self>()
953    }
954}
955
956impl<T: Timeline + Copy + 'static, U: Copy + 'static> ValueTypeMarker for Instant<T, U> {
957    type Borrowed<'a> = Self;
958    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
959        *value
960    }
961}
962
963unsafe impl<T: Timeline + Copy + 'static, D: ResourceDialect> Encode<Instant<T>, D> for Instant<T> {
964    #[inline]
965    unsafe fn encode(
966        self,
967        encoder: &mut Encoder<'_, D>,
968        offset: usize,
969        _depth: Depth,
970    ) -> Result<()> {
971        encoder.debug_check_bounds::<Self>(offset);
972        encoder.write_num(self.into_nanos(), offset);
973        Ok(())
974    }
975}
976
977unsafe impl<T: Timeline + 'static, D: ResourceDialect> Encode<Ticks<T>, D> for Ticks<T> {
978    #[inline]
979    unsafe fn encode(
980        self,
981        encoder: &mut Encoder<'_, D>,
982        offset: usize,
983        _depth: Depth,
984    ) -> Result<()> {
985        encoder.debug_check_bounds::<Self>(offset);
986        encoder.write_num(self.into_raw(), offset);
987        Ok(())
988    }
989}
990
991////////////////////////////////////////////////////////////////////////////////
992// Decoder
993////////////////////////////////////////////////////////////////////////////////
994
995/// Decoding state
996#[derive(Debug)]
997pub struct Decoder<'a, D: ResourceDialect> {
998    /// Decoding context.
999    pub context: Context,
1000
1001    /// Buffer from which to read data.
1002    pub buf: &'a [u8],
1003
1004    /// Next out of line block in buf.
1005    next_out_of_line: usize,
1006
1007    /// Buffer from which to read handles.
1008    handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
1009
1010    /// Index of the next handle to read from the handle array
1011    next_handle: usize,
1012
1013    /// The dialect determines how we encode resources.
1014    _dialect: PhantomData<D>,
1015}
1016
1017impl<'a, D: ResourceDialect> Decoder<'a, D> {
1018    /// Decodes a value of FIDL type `T` into the Rust type `T::Owned` from the
1019    /// provided data and handle buffers. Assumes the buffers came from inside a
1020    /// transaction message wrapped by `header`.
1021    #[inline]
1022    pub fn decode_into<T: TypeMarker>(
1023        header: &TransactionHeader,
1024        buf: &'a [u8],
1025        handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
1026        value: &mut T::Owned,
1027    ) -> Result<()>
1028    where
1029        T::Owned: Decode<T, D>,
1030    {
1031        Self::decode_with_context::<T>(header.decoding_context(), buf, handles, value)
1032    }
1033
1034    /// Decodes a value of FIDL type `T` into the Rust type `T::Owned` from the
1035    /// provided data and handle buffers, using the specified context.
1036    ///
1037    /// WARNING: Do not call this directly unless you know what you're doing.
1038    /// FIDL uses `Context` to coordinate soft migrations, so improper uses of
1039    /// this function could result in ABI breakage.
1040    #[inline]
1041    pub fn decode_with_context<T: TypeMarker>(
1042        context: Context,
1043        buf: &'a [u8],
1044        handles: &'a mut [<D::Handle as HandleFor<D>>::HandleInfo],
1045        value: &mut T::Owned,
1046    ) -> Result<()>
1047    where
1048        T::Owned: Decode<T, D>,
1049    {
1050        let inline_size = T::inline_size(context);
1051        let next_out_of_line = round_up_to_align(inline_size, 8);
1052        if next_out_of_line > buf.len() {
1053            return Err(Error::OutOfRange);
1054        }
1055        let mut decoder = Decoder {
1056            next_out_of_line,
1057            buf,
1058            handles,
1059            next_handle: 0,
1060            context,
1061            _dialect: PhantomData,
1062        };
1063        // Safety: buf.len() >= inline_size based on the check above.
1064        unsafe {
1065            value.decode(&mut decoder, 0, Depth(0))?;
1066        }
1067        // Safety: next_out_of_line <= buf.len() based on the check above.
1068        unsafe { decoder.post_decoding(inline_size, next_out_of_line) }
1069    }
1070
1071    /// Checks for errors after decoding. This is a separate function to reduce
1072    /// binary bloat.
1073    ///
1074    /// # Safety
1075    ///
1076    /// Requires `padding_end <= self.buf.len()`.
1077    unsafe fn post_decoding(&self, padding_start: usize, padding_end: usize) -> Result<()> {
1078        if self.next_out_of_line < self.buf.len() {
1079            return Err(Error::ExtraBytes);
1080        }
1081        if self.next_handle < self.handles.len() {
1082            return Err(Error::ExtraHandles);
1083        }
1084
1085        let padding = padding_end - padding_start;
1086        if padding > 0 {
1087            // Safety:
1088            // padding_end <= self.buf.len() is guaranteed by the caller.
1089            let last_u64 = unsafe {
1090                let last_u64_ptr = self.buf.get_unchecked(padding_end - 8) as *const u8;
1091                (last_u64_ptr as *const u64).read_unaligned()
1092            };
1093            // padding == 0 => mask == 0x0000000000000000
1094            // padding == 1 => mask == 0xff00000000000000
1095            // padding == 2 => mask == 0xffff000000000000
1096            // ...
1097            let mask = !(!0u64 >> (padding * 8));
1098            if last_u64 & mask != 0 {
1099                return Err(self.end_of_block_padding_error(padding_start, padding_end));
1100            }
1101        }
1102
1103        Ok(())
1104    }
1105
1106    /// The position of the next out of line block and the end of the current
1107    /// blocks.
1108    #[inline(always)]
1109    pub fn next_out_of_line(&self) -> usize {
1110        self.next_out_of_line
1111    }
1112
1113    /// The number of handles that have not yet been consumed.
1114    #[inline(always)]
1115    pub fn remaining_handles(&self) -> usize {
1116        self.handles.len() - self.next_handle
1117    }
1118
1119    /// In debug mode only, asserts that there is enough room in the buffer to
1120    /// read an object of type `T` at `offset`.
1121    #[inline(always)]
1122    pub fn debug_check_bounds<T: TypeMarker>(&self, offset: usize) {
1123        debug_assert!(offset + T::inline_size(self.context) <= self.buf.len());
1124    }
1125
1126    /// Decodes a primitive numeric type. The caller must ensure that `self.buf`
1127    /// has room for reading `T::inline_size` bytes as `offset`.
1128    #[inline(always)]
1129    pub fn read_num<T: numeric::Numeric>(&mut self, offset: usize) -> T {
1130        debug_assert!(offset + mem::size_of::<T>() <= self.buf.len());
1131        // Safety: The caller ensures `offset` is valid for reading
1132        // sizeof(T) bytes. Transmuting to a same-or-wider
1133        // integer pointer is safe because we use `read_unaligned`.
1134        unsafe {
1135            let ptr = self.buf.get_unchecked(offset) as *const u8;
1136            (ptr as *const T).read_unaligned()
1137        }
1138    }
1139
1140    /// Returns an offset for reading `len` out-of-line bytes. Validates that
1141    /// padding bytes at the end are zero if `len` is not a multiple of 8.
1142    ///
1143    /// # Safety
1144    ///
1145    /// The caller must ensure that `len` is nonzero.
1146    #[inline(always)]
1147    pub unsafe fn out_of_line_offset(&mut self, len: usize) -> Result<usize> {
1148        debug_assert!(len > 0);
1149        let offset = self.next_out_of_line;
1150        let aligned_len = round_up_to_align(len, 8);
1151        self.next_out_of_line += aligned_len;
1152        debug_assert!(self.next_out_of_line >= 8);
1153        if self.next_out_of_line > self.buf.len() {
1154            return Err(Error::OutOfRange);
1155        }
1156        // Validate padding bytes at the end of the block.
1157        // Safety:
1158        // - The caller ensures `len > 0`, therefore `aligned_len >= 8`.
1159        // - After `self.next_out_of_line += aligned_len`, we know `self.next_out_of_line >= aligned_len >= 8`.
1160        // - Therefore `self.next_out_of_line - 8 >= 0` is a valid *const u64.
1161        let last_u64_ptr = self.buf.get_unchecked(self.next_out_of_line - 8) as *const u8;
1162        let last_u64 = (last_u64_ptr as *const u64).read_unaligned();
1163        let padding = aligned_len - len;
1164        // padding == 0 => mask == 0x0000000000000000
1165        // padding == 1 => mask == 0xff00000000000000
1166        // padding == 2 => mask == 0xffff000000000000
1167        // ...
1168        let mask = !(!0u64 >> (padding * 8));
1169        if last_u64 & mask != 0 {
1170            return Err(self.end_of_block_padding_error(offset + len, self.next_out_of_line));
1171        }
1172
1173        Ok(offset)
1174    }
1175
1176    /// Generates an error for bad padding bytes at the end of a block.
1177    /// Assumes it is already known that there is a nonzero padding byte.
1178    fn end_of_block_padding_error(&self, start: usize, end: usize) -> Error {
1179        for i in start..end {
1180            if self.buf[i] != 0 {
1181                return Error::NonZeroPadding { padding_start: start };
1182            }
1183        }
1184        // This should be unreachable because we only call this after finding
1185        // nonzero padding. Abort instead of panicking to save code size.
1186        std::process::abort();
1187    }
1188
1189    /// Checks that the specified padding bytes are in fact zeroes. Like
1190    /// `Decode::decode`, the caller is responsible for bounds checks.
1191    #[inline]
1192    pub fn check_padding(&self, offset: usize, len: usize) -> Result<()> {
1193        if len == 0 {
1194            // Skip body (so it can be optimized out).
1195            return Ok(());
1196        }
1197        debug_assert!(offset + len <= self.buf.len());
1198        for i in offset..offset + len {
1199            // Safety: Caller guarantees offset..offset+len is in bounds.
1200            if unsafe { *self.buf.get_unchecked(i) } != 0 {
1201                return Err(Error::NonZeroPadding { padding_start: offset });
1202            }
1203        }
1204        Ok(())
1205    }
1206
1207    /// Checks the padding of the inline value portion of an envelope. Like
1208    /// `Decode::decode`, the caller is responsible for bounds checks.
1209    ///
1210    /// Note: `check_padding` could be used instead, but doing so leads to long
1211    /// compilation times which is why this method exists.
1212    #[inline]
1213    pub fn check_inline_envelope_padding(
1214        &self,
1215        value_offset: usize,
1216        value_len: usize,
1217    ) -> Result<()> {
1218        // Safety: The caller ensures `value_offset` is valid for reading
1219        // `value_len` bytes.
1220        let valid_padding = unsafe {
1221            match value_len {
1222                1 => {
1223                    *self.buf.get_unchecked(value_offset + 1) == 0
1224                        && *self.buf.get_unchecked(value_offset + 2) == 0
1225                        && *self.buf.get_unchecked(value_offset + 3) == 0
1226                }
1227                2 => {
1228                    *self.buf.get_unchecked(value_offset + 2) == 0
1229                        && *self.buf.get_unchecked(value_offset + 3) == 0
1230                }
1231                3 => *self.buf.get_unchecked(value_offset + 3) == 0,
1232                4 => true,
1233                value_len => unreachable!("value_len={}", value_len),
1234            }
1235        };
1236        if valid_padding {
1237            Ok(())
1238        } else {
1239            Err(Error::NonZeroPadding { padding_start: value_offset + value_len })
1240        }
1241    }
1242
1243    /// Take the next handle from the `handles` list.
1244    #[inline]
1245    pub fn take_next_handle(
1246        &mut self,
1247        expected_object_type: crate::ObjectType,
1248        expected_rights: crate::Rights,
1249    ) -> Result<D::Handle> {
1250        let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1251            return Err(Error::OutOfRange);
1252        };
1253        let handle = next_handle.consume(expected_object_type, expected_rights)?;
1254        self.next_handle += 1;
1255        Ok(handle)
1256    }
1257
1258    /// Drops the next handle in the handle array.
1259    #[inline]
1260    pub fn drop_next_handle(&mut self) -> Result<()> {
1261        let Some(next_handle) = self.handles.get_mut(self.next_handle) else {
1262            return Err(Error::OutOfRange);
1263        };
1264        next_handle.drop_in_place();
1265        self.next_handle += 1;
1266        Ok(())
1267    }
1268}
1269
1270impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Instant<T> {
1271    #[inline(always)]
1272    fn new_empty() -> Self {
1273        Instant::ZERO
1274    }
1275
1276    #[inline]
1277    unsafe fn decode(
1278        &mut self,
1279        decoder: &mut Decoder<'_, D>,
1280        offset: usize,
1281        _depth: Depth,
1282    ) -> Result<()> {
1283        decoder.debug_check_bounds::<Self>(offset);
1284        *self = Self::from_nanos(decoder.read_num(offset));
1285        Ok(())
1286    }
1287}
1288
1289impl<T: Timeline + 'static, D: ResourceDialect> Decode<Self, D> for Ticks<T> {
1290    #[inline(always)]
1291    fn new_empty() -> Self {
1292        Ticks::<T>::ZERO
1293    }
1294
1295    #[inline]
1296    unsafe fn decode(
1297        &mut self,
1298        decoder: &mut Decoder<'_, D>,
1299        offset: usize,
1300        _depth: Depth,
1301    ) -> Result<()> {
1302        decoder.debug_check_bounds::<Self>(offset);
1303        *self = Self::from_raw(decoder.read_num(offset));
1304        Ok(())
1305    }
1306}
1307
1308////////////////////////////////////////////////////////////////////////////////
1309// Ambiguous types
1310////////////////////////////////////////////////////////////////////////////////
1311
1312/// A fake FIDL type that can encode from and decode into any Rust type.
1313///
1314/// This exists solely to prevent the compiler from inferring `T: TypeMarker`,
1315/// allowing us to add new generic impls without source breakage. It also
1316/// improves error messages when no suitable `T: TypeMarker` exists, preventing
1317/// spurious guesses about what you should do (e.g. implement `HandleBased`).
1318pub struct Ambiguous1;
1319
1320/// Like `Ambiguous1`. There needs to be two of these types so that the compiler
1321/// doesn't infer one of them and generate a call to the panicking methods.
1322pub struct Ambiguous2;
1323
1324/// An uninhabited type used as owned and borrowed type for ambiguous markers.
1325/// Can be replaced by `!` once that is stable.
1326pub enum AmbiguousNever {}
1327
1328macro_rules! impl_ambiguous {
1329    ($ambiguous:ident) => {
1330        unsafe impl TypeMarker for $ambiguous {
1331            type Owned = AmbiguousNever;
1332
1333            fn inline_align(_context: Context) -> usize {
1334                panic!("reached code for fake ambiguous type");
1335            }
1336
1337            fn inline_size(_context: Context) -> usize {
1338                panic!("reached code for fake ambiguous type");
1339            }
1340        }
1341
1342        impl ValueTypeMarker for $ambiguous {
1343            type Borrowed<'a> = AmbiguousNever;
1344
1345            fn borrow(value: &<Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1346                match *value {}
1347            }
1348        }
1349
1350        impl ResourceTypeMarker for $ambiguous {
1351            type Borrowed<'a> = AmbiguousNever;
1352            fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_>
1353            where
1354                Self: TypeMarker,
1355            {
1356                match *value {}
1357            }
1358        }
1359
1360        unsafe impl<T, D: ResourceDialect> Encode<$ambiguous, D> for T {
1361            unsafe fn encode(
1362                self,
1363                _encoder: &mut Encoder<'_, D>,
1364                _offset: usize,
1365                _depth: Depth,
1366            ) -> Result<()> {
1367                panic!("reached code for fake ambiguous type");
1368            }
1369        }
1370
1371        // TODO(https://fxbug.dev/42069855): impl for `T: 'static` this once user code has
1372        // migrated off new_empty(), which is meant to be internal.
1373        impl<D: ResourceDialect> Decode<$ambiguous, D> for AmbiguousNever {
1374            fn new_empty() -> Self {
1375                panic!("reached code for fake ambiguous type");
1376            }
1377
1378            unsafe fn decode(
1379                &mut self,
1380                _decoder: &mut Decoder<'_, D>,
1381                _offset: usize,
1382                _depth: Depth,
1383            ) -> Result<()> {
1384                match *self {}
1385            }
1386        }
1387    };
1388}
1389
1390impl_ambiguous!(Ambiguous1);
1391impl_ambiguous!(Ambiguous2);
1392
1393////////////////////////////////////////////////////////////////////////////////
1394// Empty types
1395////////////////////////////////////////////////////////////////////////////////
1396
1397/// A FIDL type representing an empty payload (0 bytes).
1398pub struct EmptyPayload;
1399
1400unsafe impl TypeMarker for EmptyPayload {
1401    type Owned = ();
1402    #[inline(always)]
1403    fn inline_align(_context: Context) -> usize {
1404        1
1405    }
1406
1407    #[inline(always)]
1408    fn inline_size(_context: Context) -> usize {
1409        0
1410    }
1411}
1412
1413impl ValueTypeMarker for EmptyPayload {
1414    type Borrowed<'a> = ();
1415    #[inline(always)]
1416    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1417        *value
1418    }
1419}
1420
1421unsafe impl<D: ResourceDialect> Encode<EmptyPayload, D> for () {
1422    #[inline(always)]
1423    unsafe fn encode(
1424        self,
1425        _encoder: &mut Encoder<'_, D>,
1426        _offset: usize,
1427        _depth: Depth,
1428    ) -> Result<()> {
1429        Ok(())
1430    }
1431}
1432
1433impl<D: ResourceDialect> Decode<EmptyPayload, D> for () {
1434    #[inline(always)]
1435    fn new_empty() -> Self {}
1436
1437    #[inline(always)]
1438    unsafe fn decode(
1439        &mut self,
1440        _decoder: &mut Decoder<'_, D>,
1441        _offset: usize,
1442        _depth: Depth,
1443    ) -> Result<()> {
1444        Ok(())
1445    }
1446}
1447
1448/// The FIDL type used for an empty success variant in a result union. Result
1449/// unions occur in two-way methods that are flexible or that use error syntax.
1450pub struct EmptyStruct;
1451
1452unsafe impl TypeMarker for EmptyStruct {
1453    type Owned = ();
1454    #[inline(always)]
1455    fn inline_align(_context: Context) -> usize {
1456        1
1457    }
1458
1459    #[inline(always)]
1460    fn inline_size(_context: Context) -> usize {
1461        1
1462    }
1463}
1464
1465impl ValueTypeMarker for EmptyStruct {
1466    type Borrowed<'a> = ();
1467    #[inline(always)]
1468    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1469        *value
1470    }
1471}
1472
1473unsafe impl<D: ResourceDialect> Encode<EmptyStruct, D> for () {
1474    #[inline]
1475    unsafe fn encode(
1476        self,
1477        encoder: &mut Encoder<'_, D>,
1478        offset: usize,
1479        _depth: Depth,
1480    ) -> Result<()> {
1481        encoder.debug_check_bounds::<EmptyStruct>(offset);
1482        encoder.write_num(0u8, offset);
1483        Ok(())
1484    }
1485}
1486
1487impl<D: ResourceDialect> Decode<EmptyStruct, D> for () {
1488    #[inline(always)]
1489    fn new_empty() -> Self {}
1490
1491    #[inline]
1492    unsafe fn decode(
1493        &mut self,
1494        decoder: &mut Decoder<'_, D>,
1495        offset: usize,
1496        _depth: Depth,
1497    ) -> Result<()> {
1498        decoder.debug_check_bounds::<EmptyStruct>(offset);
1499        match decoder.read_num::<u8>(offset) {
1500            0 => Ok(()),
1501            _ => Err(Error::Invalid),
1502        }
1503    }
1504}
1505
1506////////////////////////////////////////////////////////////////////////////////
1507// Primitive types
1508////////////////////////////////////////////////////////////////////////////////
1509
1510// Private module to prevent others from implementing `Numeric`.
1511mod numeric {
1512    use super::*;
1513
1514    /// Marker trait for primitive numeric types.
1515    pub trait Numeric {}
1516
1517    /// Implements `Numeric`, `TypeMarker`, `ValueTypeMarker`, `Encode`, and
1518    /// `Decode` for a primitive numeric type (integer or float).
1519    macro_rules! impl_numeric {
1520        ($numeric_ty:ty) => {
1521            impl Numeric for $numeric_ty {}
1522
1523            unsafe impl TypeMarker for $numeric_ty {
1524                type Owned = $numeric_ty;
1525                #[inline(always)]
1526                fn inline_align(_context: Context) -> usize {
1527                    mem::align_of::<$numeric_ty>()
1528                }
1529
1530                #[inline(always)]
1531                fn inline_size(_context: Context) -> usize {
1532                    mem::size_of::<$numeric_ty>()
1533                }
1534
1535                #[inline(always)]
1536                fn encode_is_copy() -> bool {
1537                    true
1538                }
1539
1540                #[inline(always)]
1541                fn decode_is_copy() -> bool {
1542                    true
1543                }
1544            }
1545
1546            impl ValueTypeMarker for $numeric_ty {
1547                type Borrowed<'a> = $numeric_ty;
1548
1549                #[inline(always)]
1550                fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1551                    *value
1552                }
1553            }
1554
1555            unsafe impl<D: ResourceDialect> Encode<$numeric_ty, D> for $numeric_ty {
1556                #[inline(always)]
1557                unsafe fn encode(
1558                    self,
1559                    encoder: &mut Encoder<'_, D>,
1560                    offset: usize,
1561                    _depth: Depth,
1562                ) -> Result<()> {
1563                    encoder.debug_check_bounds::<$numeric_ty>(offset);
1564                    encoder.write_num::<$numeric_ty>(self, offset);
1565                    Ok(())
1566                }
1567            }
1568
1569            impl<D: ResourceDialect> Decode<$numeric_ty, D> for $numeric_ty {
1570                #[inline(always)]
1571                fn new_empty() -> Self {
1572                    0 as $numeric_ty
1573                }
1574
1575                #[inline(always)]
1576                unsafe fn decode(
1577                    &mut self,
1578                    decoder: &mut Decoder<'_, D>,
1579                    offset: usize,
1580                    _depth: Depth,
1581                ) -> Result<()> {
1582                    decoder.debug_check_bounds::<$numeric_ty>(offset);
1583                    *self = decoder.read_num::<$numeric_ty>(offset);
1584                    Ok(())
1585                }
1586            }
1587        };
1588    }
1589
1590    impl_numeric!(u8);
1591    impl_numeric!(u16);
1592    impl_numeric!(u32);
1593    impl_numeric!(u64);
1594    impl_numeric!(i8);
1595    impl_numeric!(i16);
1596    impl_numeric!(i32);
1597    impl_numeric!(i64);
1598    impl_numeric!(f32);
1599    impl_numeric!(f64);
1600}
1601
1602unsafe impl TypeMarker for bool {
1603    type Owned = bool;
1604
1605    #[inline(always)]
1606    fn inline_align(_context: Context) -> usize {
1607        mem::align_of::<bool>()
1608    }
1609
1610    #[inline(always)]
1611    fn inline_size(_context: Context) -> usize {
1612        mem::size_of::<bool>()
1613    }
1614
1615    #[inline(always)]
1616    fn encode_is_copy() -> bool {
1617        // Rust guarantees a bool is 0x00 or 0x01.
1618        // https://doc.rust-lang.org/reference/types/boolean.html
1619        true
1620    }
1621
1622    #[inline(always)]
1623    fn decode_is_copy() -> bool {
1624        // Decoding isn't just a copy because we have to ensure it's 0x00 or 0x01.
1625        false
1626    }
1627}
1628
1629impl ValueTypeMarker for bool {
1630    type Borrowed<'a> = bool;
1631
1632    #[inline(always)]
1633    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1634        *value
1635    }
1636}
1637
1638unsafe impl<D: ResourceDialect> Encode<bool, D> for bool {
1639    #[inline]
1640    unsafe fn encode(
1641        self,
1642        encoder: &mut Encoder<'_, D>,
1643        offset: usize,
1644        _depth: Depth,
1645    ) -> Result<()> {
1646        encoder.debug_check_bounds::<bool>(offset);
1647        // From https://doc.rust-lang.org/std/primitive.bool.html: "If you
1648        // cast a bool into an integer, true will be 1 and false will be 0."
1649        encoder.write_num(self as u8, offset);
1650        Ok(())
1651    }
1652}
1653
1654impl<D: ResourceDialect> Decode<bool, D> for bool {
1655    #[inline(always)]
1656    fn new_empty() -> Self {
1657        false
1658    }
1659
1660    #[inline]
1661    unsafe fn decode(
1662        &mut self,
1663        decoder: &mut Decoder<'_, D>,
1664        offset: usize,
1665        _depth: Depth,
1666    ) -> Result<()> {
1667        decoder.debug_check_bounds::<bool>(offset);
1668        // Safety: The caller ensures `offset` is valid for reading 1 byte.
1669        *self = match unsafe { *decoder.buf.get_unchecked(offset) } {
1670            0 => false,
1671            1 => true,
1672            _ => return Err(Error::InvalidBoolean),
1673        };
1674        Ok(())
1675    }
1676}
1677
1678////////////////////////////////////////////////////////////////////////////////
1679// Arrays
1680////////////////////////////////////////////////////////////////////////////////
1681
1682/// The FIDL type `array<T, N>`.
1683pub struct Array<T: TypeMarker, const N: usize>(PhantomData<T>);
1684
1685unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Array<T, N> {
1686    type Owned = [T::Owned; N];
1687    #[inline(always)]
1688    fn inline_align(context: Context) -> usize {
1689        T::inline_align(context)
1690    }
1691
1692    #[inline(always)]
1693    fn inline_size(context: Context) -> usize {
1694        N * T::inline_size(context)
1695    }
1696
1697    #[inline(always)]
1698    fn encode_is_copy() -> bool {
1699        T::encode_is_copy()
1700    }
1701
1702    #[inline(always)]
1703    fn decode_is_copy() -> bool {
1704        T::decode_is_copy()
1705    }
1706}
1707
1708impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Array<T, N> {
1709    type Borrowed<'a> = &'a [T::Owned; N];
1710    #[inline(always)]
1711    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1712        value
1713    }
1714}
1715
1716impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Array<T, N> {
1717    type Borrowed<'a> = &'a mut [T::Owned; N];
1718    #[inline(always)]
1719    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1720        value
1721    }
1722}
1723
1724unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1725    for &[T::Owned; N]
1726where
1727    for<'q> T::Borrowed<'q>: Encode<T, D>,
1728{
1729    #[inline]
1730    unsafe fn encode(
1731        self,
1732        encoder: &mut Encoder<'_, D>,
1733        offset: usize,
1734        depth: Depth,
1735    ) -> Result<()> {
1736        encoder.debug_check_bounds::<Array<T, N>>(offset);
1737        encode_array_value::<T, D>(self, encoder, offset, depth)
1738    }
1739}
1740
1741unsafe impl<T: ResourceTypeMarker, const N: usize, D: ResourceDialect> Encode<Array<T, N>, D>
1742    for &mut [<T as TypeMarker>::Owned; N]
1743where
1744    for<'q> T::Borrowed<'q>: Encode<T, D>,
1745{
1746    #[inline]
1747    unsafe fn encode(
1748        self,
1749        encoder: &mut Encoder<'_, D>,
1750        offset: usize,
1751        depth: Depth,
1752    ) -> Result<()> {
1753        encoder.debug_check_bounds::<Array<T, N>>(offset);
1754        encode_array_resource::<T, D>(self, encoder, offset, depth)
1755    }
1756}
1757
1758impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Array<T, N>, D> for [T::Owned; N]
1759where
1760    T::Owned: Decode<T, D>,
1761{
1762    #[inline]
1763    fn new_empty() -> Self {
1764        let mut arr = mem::MaybeUninit::<[T::Owned; N]>::uninit();
1765        unsafe {
1766            let arr_ptr = arr.as_mut_ptr() as *mut T::Owned;
1767            for i in 0..N {
1768                ptr::write(arr_ptr.add(i), T::Owned::new_empty());
1769            }
1770            arr.assume_init()
1771        }
1772    }
1773
1774    #[inline]
1775    unsafe fn decode(
1776        &mut self,
1777        decoder: &mut Decoder<'_, D>,
1778        offset: usize,
1779        depth: Depth,
1780    ) -> Result<()> {
1781        decoder.debug_check_bounds::<Array<T, N>>(offset);
1782        decode_array::<T, D>(self, decoder, offset, depth)
1783    }
1784}
1785
1786#[inline]
1787unsafe fn encode_array_value<T: ValueTypeMarker, D: ResourceDialect>(
1788    slice: &[T::Owned],
1789    encoder: &mut Encoder<'_, D>,
1790    offset: usize,
1791    depth: Depth,
1792) -> Result<()>
1793where
1794    for<'a> T::Borrowed<'a>: Encode<T, D>,
1795{
1796    let stride = T::inline_size(encoder.context);
1797    let len = slice.len();
1798    // Not a safety requirement, but len should be nonzero since FIDL does not allow empty arrays.
1799    debug_assert_ne!(len, 0);
1800    if T::encode_is_copy() {
1801        debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1802        // Safety:
1803        // - The caller ensures `offset` if valid for writing `stride` bytes
1804        //   (inline size of `T`) `len` times, i.e. `len * stride`.
1805        // - Since T::inline_size is the same as mem::size_of for simple
1806        //   copy types, `slice` also has exactly `len * stride` bytes.
1807        // - Rust guarantees `slice` and `encoder.buf` do not alias.
1808        unsafe {
1809            let src = slice.as_ptr() as *const u8;
1810            let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1811            ptr::copy_nonoverlapping(src, dst, len * stride);
1812        }
1813    } else {
1814        for i in 0..len {
1815            // Safety: `i` is in bounds since `len` is defined as `slice.len()`.
1816            let item = unsafe { slice.get_unchecked(i) };
1817            T::borrow(item).encode(encoder, offset + i * stride, depth)?;
1818        }
1819    }
1820    Ok(())
1821}
1822
1823#[inline]
1824unsafe fn encode_array_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
1825    slice: &mut [T::Owned],
1826    encoder: &mut Encoder<'_, D>,
1827    offset: usize,
1828    depth: Depth,
1829) -> Result<()>
1830where
1831    for<'a> T::Borrowed<'a>: Encode<T, D>,
1832{
1833    let stride = T::inline_size(encoder.context);
1834    let len = slice.len();
1835    // Not a safety requirement, but len should be nonzero since FIDL does not allow empty arrays.
1836    debug_assert_ne!(len, 0);
1837    if T::encode_is_copy() {
1838        debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1839        // Safety:
1840        // - The caller ensures `offset` if valid for writing `stride` bytes
1841        //   (inline size of `T`) `len` times, i.e. `len * stride`.
1842        // - Since T::inline_size is the same as mem::size_of for simple
1843        //   copy types, `slice` also has exactly `len * stride` bytes.
1844        // - Rust guarantees `slice` and `encoder.buf` do not alias.
1845        unsafe {
1846            let src = slice.as_ptr() as *const u8;
1847            let dst: *mut u8 = encoder.buf.as_mut_ptr().add(offset);
1848            ptr::copy_nonoverlapping(src, dst, len * stride);
1849        }
1850    } else {
1851        for i in 0..len {
1852            // Safety: `i` is in bounds since `len` is defined as `slice.len()`.
1853            let item = unsafe { slice.get_unchecked_mut(i) };
1854            T::take_or_borrow(item).encode(encoder, offset + i * stride, depth)?;
1855        }
1856    }
1857    Ok(())
1858}
1859
1860#[inline]
1861unsafe fn decode_array<T: TypeMarker, D: ResourceDialect>(
1862    slice: &mut [T::Owned],
1863    decoder: &mut Decoder<'_, D>,
1864    offset: usize,
1865    depth: Depth,
1866) -> Result<()>
1867where
1868    T::Owned: Decode<T, D>,
1869{
1870    let stride = T::inline_size(decoder.context);
1871    let len = slice.len();
1872    // Not a safety requirement, but len should be nonzero since FIDL does not allow empty arrays.
1873    debug_assert_ne!(len, 0);
1874    if T::decode_is_copy() {
1875        debug_assert_eq!(stride, mem::size_of::<T::Owned>());
1876        // Safety:
1877        // - The caller ensures `offset` if valid for reading `stride` bytes
1878        //   (inline size of `T`) `len` times, i.e. `len * stride`.
1879        // - Since T::inline_size is the same as mem::size_of for simple copy
1880        //   types, `slice` also has exactly `len * stride` bytes.
1881        // - Rust guarantees `slice` and `decoder.buf` do not alias.
1882        unsafe {
1883            let src: *const u8 = decoder.buf.as_ptr().add(offset);
1884            let dst = slice.as_mut_ptr() as *mut u8;
1885            ptr::copy_nonoverlapping(src, dst, len * stride);
1886        }
1887    } else {
1888        for i in 0..len {
1889            // Safety: `i` is in bounds since `len` is defined as `slice.len()`.
1890            let item = unsafe { slice.get_unchecked_mut(i) };
1891            item.decode(decoder, offset + i * stride, depth)?;
1892        }
1893    }
1894    Ok(())
1895}
1896
1897////////////////////////////////////////////////////////////////////////////////
1898// Vectors
1899////////////////////////////////////////////////////////////////////////////////
1900
1901/// The maximum vector bound, corresponding to the `MAX` constraint in FIDL.
1902pub const MAX_BOUND: usize = usize::MAX;
1903
1904/// The FIDL type `vector<T>:N`.
1905pub struct Vector<T: TypeMarker, const N: usize>(PhantomData<T>);
1906
1907/// The FIDL type `vector<T>` or `vector<T>:MAX`.
1908pub type UnboundedVector<T> = Vector<T, MAX_BOUND>;
1909
1910unsafe impl<T: TypeMarker, const N: usize> TypeMarker for Vector<T, N> {
1911    type Owned = Vec<T::Owned>;
1912
1913    #[inline(always)]
1914    fn inline_align(_context: Context) -> usize {
1915        8
1916    }
1917
1918    #[inline(always)]
1919    fn inline_size(_context: Context) -> usize {
1920        16
1921    }
1922}
1923
1924impl<T: ValueTypeMarker, const N: usize> ValueTypeMarker for Vector<T, N> {
1925    type Borrowed<'a> = &'a [T::Owned];
1926    #[inline(always)]
1927    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
1928        value
1929    }
1930}
1931
1932impl<T: ResourceTypeMarker, const N: usize> ResourceTypeMarker for Vector<T, N> {
1933    type Borrowed<'a> = &'a mut [T::Owned];
1934    #[inline(always)]
1935    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
1936        value.as_mut_slice()
1937    }
1938}
1939
1940unsafe impl<T: ValueTypeMarker, const N: usize, D: ResourceDialect> Encode<Vector<T, N>, D>
1941    for &[<T as TypeMarker>::Owned]
1942where
1943    for<'q> T::Borrowed<'q>: Encode<T, D>,
1944{
1945    #[inline]
1946    unsafe fn encode(
1947        self,
1948        encoder: &mut Encoder<'_, D>,
1949        offset: usize,
1950        depth: Depth,
1951    ) -> Result<()> {
1952        encoder.debug_check_bounds::<Vector<T, N>>(offset);
1953        encode_vector_value::<T, D>(self, N, check_vector_length, encoder, offset, depth)
1954    }
1955}
1956
1957unsafe impl<T: ResourceTypeMarker + TypeMarker, const N: usize, D: ResourceDialect>
1958    Encode<Vector<T, N>, D> for &mut [<T as TypeMarker>::Owned]
1959where
1960    for<'q> T::Borrowed<'q>: Encode<T, D>,
1961{
1962    #[inline]
1963    unsafe fn encode(
1964        self,
1965        encoder: &mut Encoder<'_, D>,
1966        offset: usize,
1967        depth: Depth,
1968    ) -> Result<()> {
1969        encoder.debug_check_bounds::<Vector<T, N>>(offset);
1970        encode_vector_resource::<T, D>(self, N, encoder, offset, depth)
1971    }
1972}
1973
1974impl<T: TypeMarker, const N: usize, D: ResourceDialect> Decode<Vector<T, N>, D> for Vec<T::Owned>
1975where
1976    T::Owned: Decode<T, D>,
1977{
1978    #[inline(always)]
1979    fn new_empty() -> Self {
1980        Vec::new()
1981    }
1982
1983    #[inline]
1984    unsafe fn decode(
1985        &mut self,
1986        decoder: &mut Decoder<'_, D>,
1987        offset: usize,
1988        depth: Depth,
1989    ) -> Result<()> {
1990        decoder.debug_check_bounds::<Vector<T, N>>(offset);
1991        decode_vector::<T, D>(self, N, decoder, offset, depth)
1992    }
1993}
1994
1995#[inline]
1996unsafe fn encode_vector_value<T: ValueTypeMarker, D: ResourceDialect>(
1997    slice: &[<T as TypeMarker>::Owned],
1998    max_length: usize,
1999    check_length: impl Fn(usize, usize) -> Result<()>,
2000    encoder: &mut Encoder<'_, D>,
2001    offset: usize,
2002    mut depth: Depth,
2003) -> Result<()>
2004where
2005    for<'a> T::Borrowed<'a>: Encode<T, D>,
2006{
2007    encoder.write_num(slice.len() as u64, offset);
2008    encoder.write_num(ALLOC_PRESENT_U64, offset + 8);
2009    // Calling encoder.out_of_line_offset(0) is not allowed.
2010    if slice.is_empty() {
2011        return Ok(());
2012    }
2013    check_length(slice.len(), max_length)?;
2014    depth.increment()?;
2015    let bytes_len = slice.len() * T::inline_size(encoder.context);
2016    let offset = encoder.out_of_line_offset(bytes_len);
2017    encode_array_value::<T, D>(slice, encoder, offset, depth)
2018}
2019
2020#[inline]
2021unsafe fn encode_vector_resource<T: ResourceTypeMarker + TypeMarker, D: ResourceDialect>(
2022    slice: &mut [T::Owned],
2023    max_length: usize,
2024    encoder: &mut Encoder<'_, D>,
2025    offset: usize,
2026    mut depth: Depth,
2027) -> Result<()>
2028where
2029    for<'a> T::Borrowed<'a>: Encode<T, D>,
2030{
2031    encoder.write_num(slice.len() as u64, offset);
2032    encoder.write_num(ALLOC_PRESENT_U64, offset + 8);
2033    // Calling encoder.out_of_line_offset(0) is not allowed.
2034    if slice.is_empty() {
2035        return Ok(());
2036    }
2037    check_vector_length(slice.len(), max_length)?;
2038    depth.increment()?;
2039    let bytes_len = slice.len() * T::inline_size(encoder.context);
2040    let offset = encoder.out_of_line_offset(bytes_len);
2041    encode_array_resource::<T, D>(slice, encoder, offset, depth)
2042}
2043
2044#[inline]
2045unsafe fn decode_vector<T: TypeMarker, D: ResourceDialect>(
2046    vec: &mut Vec<T::Owned>,
2047    max_length: usize,
2048    decoder: &mut Decoder<'_, D>,
2049    offset: usize,
2050    mut depth: Depth,
2051) -> Result<()>
2052where
2053    T::Owned: Decode<T, D>,
2054{
2055    let Some(len) = decode_vector_header(decoder, offset)? else {
2056        return Err(Error::NotNullable);
2057    };
2058    // Calling decoder.out_of_line_offset(0) is not allowed.
2059    if len == 0 {
2060        return Ok(());
2061    }
2062    check_vector_length(len, max_length)?;
2063    depth.increment()?;
2064    let bytes_len = len * T::inline_size(decoder.context);
2065    let offset = decoder.out_of_line_offset(bytes_len)?;
2066    if T::decode_is_copy() {
2067        // Safety: The uninitialized elements are immediately written by
2068        // `decode_array`, which always succeeds in the simple copy case.
2069        unsafe {
2070            resize_vec_no_zeroing(vec, len);
2071        }
2072    } else {
2073        vec.resize_with(len, T::Owned::new_empty);
2074    }
2075    // Safety: `vec` has `len` elements based on the above code.
2076    decode_array::<T, D>(vec, decoder, offset, depth)?;
2077    Ok(())
2078}
2079
2080/// Decodes and validates a 16-byte vector header. Returns `Some(len)` if
2081/// the vector is present (including empty vectors), otherwise `None`.
2082#[doc(hidden)] // only exported for use in macros or generated code
2083#[inline]
2084pub fn decode_vector_header<D: ResourceDialect>(
2085    decoder: &mut Decoder<'_, D>,
2086    offset: usize,
2087) -> Result<Option<usize>> {
2088    let len = decoder.read_num::<u64>(offset) as usize;
2089    match decoder.read_num::<u64>(offset + 8) {
2090        ALLOC_PRESENT_U64 => {
2091            // Check that the length does not exceed `u32::MAX` (per RFC-0059)
2092            // nor the total size of the message (to avoid a huge allocation
2093            // when the message cannot possibly be valid).
2094            if len <= u32::MAX as usize && len <= decoder.buf.len() {
2095                Ok(Some(len))
2096            } else {
2097                Err(Error::OutOfRange)
2098            }
2099        }
2100        ALLOC_ABSENT_U64 => {
2101            if len == 0 {
2102                Ok(None)
2103            } else {
2104                Err(Error::UnexpectedNullRef)
2105            }
2106        }
2107        _ => Err(Error::InvalidPresenceIndicator),
2108    }
2109}
2110
2111#[inline(always)]
2112fn check_vector_length(actual_length: usize, max_length: usize) -> Result<()> {
2113    if actual_length > max_length {
2114        return Err(Error::VectorTooLong { max_length, actual_length });
2115    }
2116    Ok(())
2117}
2118
2119////////////////////////////////////////////////////////////////////////////////
2120// Strings
2121////////////////////////////////////////////////////////////////////////////////
2122
2123/// The FIDL type `string:N`.
2124pub struct BoundedString<const N: usize>;
2125
2126/// The FIDL type `string` or `string:MAX`.
2127pub type UnboundedString = BoundedString<MAX_BOUND>;
2128
2129unsafe impl<const N: usize> TypeMarker for BoundedString<N> {
2130    type Owned = String;
2131
2132    #[inline(always)]
2133    fn inline_align(_context: Context) -> usize {
2134        8
2135    }
2136
2137    #[inline(always)]
2138    fn inline_size(_context: Context) -> usize {
2139        16
2140    }
2141}
2142
2143impl<const N: usize> ValueTypeMarker for BoundedString<N> {
2144    type Borrowed<'a> = &'a str;
2145    #[inline(always)]
2146    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2147        value
2148    }
2149}
2150
2151unsafe impl<const N: usize, D: ResourceDialect> Encode<BoundedString<N>, D> for &str {
2152    #[inline]
2153    unsafe fn encode(
2154        self,
2155        encoder: &mut Encoder<'_, D>,
2156        offset: usize,
2157        depth: Depth,
2158    ) -> Result<()> {
2159        encoder.debug_check_bounds::<BoundedString<N>>(offset);
2160        encode_vector_value::<u8, D>(
2161            self.as_bytes(),
2162            N,
2163            check_string_length,
2164            encoder,
2165            offset,
2166            depth,
2167        )
2168    }
2169}
2170
2171impl<const N: usize, D: ResourceDialect> Decode<BoundedString<N>, D> for String {
2172    #[inline(always)]
2173    fn new_empty() -> Self {
2174        String::new()
2175    }
2176
2177    #[inline]
2178    unsafe fn decode(
2179        &mut self,
2180        decoder: &mut Decoder<'_, D>,
2181        offset: usize,
2182        depth: Depth,
2183    ) -> Result<()> {
2184        decoder.debug_check_bounds::<BoundedString<N>>(offset);
2185        decode_string(self, N, decoder, offset, depth)
2186    }
2187}
2188
2189#[inline]
2190fn decode_string<D: ResourceDialect>(
2191    string: &mut String,
2192    max_length: usize,
2193    decoder: &mut Decoder<'_, D>,
2194    offset: usize,
2195    mut depth: Depth,
2196) -> Result<()> {
2197    let Some(len) = decode_vector_header(decoder, offset)? else {
2198        return Err(Error::NotNullable);
2199    };
2200    // Calling decoder.out_of_line_offset(0) is not allowed.
2201    if len == 0 {
2202        return Ok(());
2203    }
2204    check_string_length(len, max_length)?;
2205    depth.increment()?;
2206    // Safety: we return early above if `len == 0`.
2207    let offset = unsafe { decoder.out_of_line_offset(len)? };
2208    // Safety: `out_of_line_offset` does this bounds check.
2209    let bytes = unsafe { &decoder.buf.get_unchecked(offset..offset + len) };
2210    let utf8 = str::from_utf8(bytes).map_err(|_| Error::Utf8Error)?;
2211    let boxed_utf8: Box<str> = utf8.into();
2212    *string = boxed_utf8.into_string();
2213    Ok(())
2214}
2215
2216#[inline(always)]
2217fn check_string_length(actual_bytes: usize, max_bytes: usize) -> Result<()> {
2218    if actual_bytes > max_bytes {
2219        return Err(Error::StringTooLong { max_bytes, actual_bytes });
2220    }
2221    Ok(())
2222}
2223
2224////////////////////////////////////////////////////////////////////////////////
2225// Handles
2226////////////////////////////////////////////////////////////////////////////////
2227
2228impl<T: HandleBased> EncodableAsHandle for T {
2229    type Dialect = DefaultFuchsiaResourceDialect;
2230}
2231
2232/// The FIDL type `zx.Handle:<OBJECT_TYPE, RIGHTS>`, or a `client_end` or `server_end`.
2233pub struct HandleType<T: EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>(
2234    PhantomData<T>,
2235);
2236
2237/// An abbreviation of `HandleType` that for channels with default rights, used
2238/// for the FIDL types `client_end:P` and `server_end:P`.
2239pub type Endpoint<T> = HandleType<
2240    T,
2241    { crate::ObjectType::CHANNEL.into_raw() },
2242    { crate::Rights::CHANNEL_DEFAULT.bits() },
2243>;
2244
2245unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> TypeMarker
2246    for HandleType<T, OBJECT_TYPE, RIGHTS>
2247{
2248    type Owned = T;
2249
2250    #[inline(always)]
2251    fn inline_align(_context: Context) -> usize {
2252        4
2253    }
2254
2255    #[inline(always)]
2256    fn inline_size(_context: Context) -> usize {
2257        4
2258    }
2259}
2260
2261impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32> ResourceTypeMarker
2262    for HandleType<T, OBJECT_TYPE, RIGHTS>
2263{
2264    type Borrowed<'a> = T;
2265    #[inline(always)]
2266    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2267        mem::replace(value, <T::Dialect as ResourceDialect>::Handle::invalid().into())
2268    }
2269}
2270
2271unsafe impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2272    Encode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2273{
2274    #[inline]
2275    unsafe fn encode(
2276        self,
2277        encoder: &mut Encoder<'_, T::Dialect>,
2278        offset: usize,
2279        _depth: Depth,
2280    ) -> Result<()> {
2281        encoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2282        encode_handle(
2283            self.into(),
2284            crate::ObjectType::from_raw(OBJECT_TYPE),
2285            crate::Rights::from_bits_retain(RIGHTS),
2286            encoder,
2287            offset,
2288        )
2289    }
2290}
2291
2292impl<T: 'static + EncodableAsHandle, const OBJECT_TYPE: u32, const RIGHTS: u32>
2293    Decode<HandleType<T, OBJECT_TYPE, RIGHTS>, T::Dialect> for T
2294{
2295    #[inline(always)]
2296    fn new_empty() -> Self {
2297        <T::Dialect as ResourceDialect>::Handle::invalid().into()
2298    }
2299
2300    #[inline]
2301    unsafe fn decode(
2302        &mut self,
2303        decoder: &mut Decoder<'_, T::Dialect>,
2304        offset: usize,
2305        _depth: Depth,
2306    ) -> Result<()> {
2307        decoder.debug_check_bounds::<HandleType<T, OBJECT_TYPE, RIGHTS>>(offset);
2308        *self = decode_handle(
2309            crate::ObjectType::from_raw(OBJECT_TYPE),
2310            crate::Rights::from_bits_retain(RIGHTS),
2311            decoder,
2312            offset,
2313        )?
2314        .into();
2315        Ok(())
2316    }
2317}
2318
2319#[inline]
2320unsafe fn encode_handle<D: ResourceDialect>(
2321    handle: D::Handle,
2322    object_type: crate::ObjectType,
2323    rights: crate::Rights,
2324    encoder: &mut Encoder<'_, D>,
2325    offset: usize,
2326) -> Result<()> {
2327    if handle.is_invalid() {
2328        return Err(Error::NotNullable);
2329    }
2330    encoder.write_num(ALLOC_PRESENT_U32, offset);
2331    encoder.handles.push(<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition::from_handle(
2332        handle,
2333        object_type,
2334        rights,
2335    ));
2336    Ok(())
2337}
2338
2339#[inline]
2340unsafe fn decode_handle<D: ResourceDialect>(
2341    object_type: crate::ObjectType,
2342    rights: crate::Rights,
2343    decoder: &mut Decoder<'_, D>,
2344    offset: usize,
2345) -> Result<D::Handle> {
2346    match decoder.read_num::<u32>(offset) {
2347        ALLOC_PRESENT_U32 => {}
2348        ALLOC_ABSENT_U32 => return Err(Error::NotNullable),
2349        _ => return Err(Error::InvalidPresenceIndicator),
2350    }
2351    decoder.take_next_handle(object_type, rights)
2352}
2353
2354////////////////////////////////////////////////////////////////////////////////
2355// Optionals
2356////////////////////////////////////////////////////////////////////////////////
2357
2358/// The FIDL type `T:optional` where `T` is a vector, string, handle, or client/server end.
2359pub struct Optional<T: TypeMarker>(PhantomData<T>);
2360
2361/// The FIDL type `T:optional` where `T` is a union.
2362pub struct OptionalUnion<T: TypeMarker>(PhantomData<T>);
2363
2364/// The FIDL type `box<T>`.
2365pub struct Boxed<T: TypeMarker>(PhantomData<T>);
2366
2367unsafe impl<T: TypeMarker> TypeMarker for Optional<T> {
2368    type Owned = Option<T::Owned>;
2369
2370    #[inline(always)]
2371    fn inline_align(context: Context) -> usize {
2372        T::inline_align(context)
2373    }
2374
2375    #[inline(always)]
2376    fn inline_size(context: Context) -> usize {
2377        T::inline_size(context)
2378    }
2379}
2380
2381unsafe impl<T: TypeMarker> TypeMarker for OptionalUnion<T> {
2382    type Owned = Option<Box<T::Owned>>;
2383
2384    #[inline(always)]
2385    fn inline_align(context: Context) -> usize {
2386        T::inline_align(context)
2387    }
2388
2389    #[inline(always)]
2390    fn inline_size(context: Context) -> usize {
2391        T::inline_size(context)
2392    }
2393}
2394
2395unsafe impl<T: TypeMarker> TypeMarker for Boxed<T> {
2396    type Owned = Option<Box<T::Owned>>;
2397
2398    #[inline(always)]
2399    fn inline_align(_context: Context) -> usize {
2400        8
2401    }
2402
2403    #[inline(always)]
2404    fn inline_size(_context: Context) -> usize {
2405        8
2406    }
2407}
2408
2409impl<T: ValueTypeMarker> ValueTypeMarker for Optional<T> {
2410    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2411
2412    #[inline(always)]
2413    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2414        value.as_ref().map(T::borrow)
2415    }
2416}
2417
2418impl<T: ValueTypeMarker> ValueTypeMarker for OptionalUnion<T> {
2419    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2420
2421    #[inline(always)]
2422    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2423        value.as_deref().map(T::borrow)
2424    }
2425}
2426
2427impl<T: ValueTypeMarker> ValueTypeMarker for Boxed<T> {
2428    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2429
2430    #[inline(always)]
2431    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2432        value.as_deref().map(T::borrow)
2433    }
2434}
2435
2436impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Optional<T> {
2437    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2438    #[inline(always)]
2439    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2440        value.as_mut().map(T::take_or_borrow)
2441    }
2442}
2443
2444impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for OptionalUnion<T> {
2445    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2446    #[inline(always)]
2447    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2448        value.as_deref_mut().map(T::take_or_borrow)
2449    }
2450}
2451
2452impl<T: ResourceTypeMarker + TypeMarker> ResourceTypeMarker for Boxed<T> {
2453    type Borrowed<'a> = Option<T::Borrowed<'a>>;
2454    #[inline(always)]
2455    fn take_or_borrow(value: &mut <Self as TypeMarker>::Owned) -> Self::Borrowed<'_> {
2456        value.as_deref_mut().map(T::take_or_borrow)
2457    }
2458}
2459
2460unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Optional<T>, D>
2461    for Option<E>
2462{
2463    #[inline]
2464    unsafe fn encode(
2465        self,
2466        encoder: &mut Encoder<'_, D>,
2467        offset: usize,
2468        depth: Depth,
2469    ) -> Result<()> {
2470        encoder.debug_check_bounds::<Optional<T>>(offset);
2471        encode_naturally_optional::<T, E, D>(self, encoder, offset, depth)
2472    }
2473}
2474
2475unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<OptionalUnion<T>, D>
2476    for Option<E>
2477{
2478    #[inline]
2479    unsafe fn encode(
2480        self,
2481        encoder: &mut Encoder<'_, D>,
2482        offset: usize,
2483        depth: Depth,
2484    ) -> Result<()> {
2485        encoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2486        encode_naturally_optional::<T, E, D>(self, encoder, offset, depth)
2487    }
2488}
2489
2490unsafe impl<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect> Encode<Boxed<T>, D> for Option<E> {
2491    #[inline]
2492    unsafe fn encode(
2493        self,
2494        encoder: &mut Encoder<'_, D>,
2495        offset: usize,
2496        mut depth: Depth,
2497    ) -> Result<()> {
2498        encoder.debug_check_bounds::<Boxed<T>>(offset);
2499        match self {
2500            Some(val) => {
2501                depth.increment()?;
2502                encoder.write_num(ALLOC_PRESENT_U64, offset);
2503                let offset = encoder.out_of_line_offset(T::inline_size(encoder.context));
2504                val.encode(encoder, offset, depth)?;
2505            }
2506            None => encoder.write_num(ALLOC_ABSENT_U64, offset),
2507        }
2508        Ok(())
2509    }
2510}
2511
2512impl<T: TypeMarker, D: ResourceDialect> Decode<Optional<T>, D> for Option<T::Owned>
2513where
2514    T::Owned: Decode<T, D>,
2515{
2516    #[inline(always)]
2517    fn new_empty() -> Self {
2518        None
2519    }
2520
2521    #[inline]
2522    unsafe fn decode(
2523        &mut self,
2524        decoder: &mut Decoder<'_, D>,
2525        offset: usize,
2526        depth: Depth,
2527    ) -> Result<()> {
2528        decoder.debug_check_bounds::<Optional<T>>(offset);
2529        let inline_size = T::inline_size(decoder.context);
2530        if check_for_presence(decoder, offset, inline_size) {
2531            self.get_or_insert(T::Owned::new_empty()).decode(decoder, offset, depth)
2532        } else {
2533            *self = None;
2534            decoder.check_padding(offset, inline_size)?;
2535            Ok(())
2536        }
2537    }
2538}
2539
2540impl<T: TypeMarker, D: ResourceDialect> Decode<OptionalUnion<T>, D> for Option<Box<T::Owned>>
2541where
2542    T::Owned: Decode<T, D>,
2543{
2544    #[inline(always)]
2545    fn new_empty() -> Self {
2546        None
2547    }
2548
2549    #[inline]
2550    unsafe fn decode(
2551        &mut self,
2552        decoder: &mut Decoder<'_, D>,
2553        offset: usize,
2554        depth: Depth,
2555    ) -> Result<()> {
2556        decoder.debug_check_bounds::<OptionalUnion<T>>(offset);
2557        let inline_size = T::inline_size(decoder.context);
2558        if check_for_presence(decoder, offset, inline_size) {
2559            decode!(
2560                T,
2561                self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2562                decoder,
2563                offset,
2564                depth
2565            )
2566        } else {
2567            *self = None;
2568            decoder.check_padding(offset, inline_size)?;
2569            Ok(())
2570        }
2571    }
2572}
2573
2574impl<T: TypeMarker, D: ResourceDialect> Decode<Boxed<T>, D> for Option<Box<T::Owned>>
2575where
2576    T::Owned: Decode<T, D>,
2577{
2578    #[inline(always)]
2579    fn new_empty() -> Self {
2580        None
2581    }
2582
2583    #[inline]
2584    unsafe fn decode(
2585        &mut self,
2586        decoder: &mut Decoder<'_, D>,
2587        offset: usize,
2588        mut depth: Depth,
2589    ) -> Result<()> {
2590        decoder.debug_check_bounds::<Boxed<T>>(offset);
2591        match decoder.read_num::<u64>(offset) {
2592            ALLOC_PRESENT_U64 => {
2593                depth.increment()?;
2594                let offset = decoder.out_of_line_offset(T::inline_size(decoder.context))?;
2595                decode!(
2596                    T,
2597                    self.get_or_insert_with(|| Box::new(T::Owned::new_empty())),
2598                    decoder,
2599                    offset,
2600                    depth
2601                )?;
2602                Ok(())
2603            }
2604            ALLOC_ABSENT_U64 => {
2605                *self = None;
2606                Ok(())
2607            }
2608            _ => Err(Error::InvalidPresenceIndicator),
2609        }
2610    }
2611}
2612
2613/// Encodes a "naturally optional" value, i.e. one where absence is represented
2614/// by a run of 0x00 bytes matching the type's inline size.
2615#[inline]
2616unsafe fn encode_naturally_optional<T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>(
2617    value: Option<E>,
2618    encoder: &mut Encoder<'_, D>,
2619    offset: usize,
2620    depth: Depth,
2621) -> Result<()> {
2622    match value {
2623        Some(val) => val.encode(encoder, offset, depth)?,
2624        None => encoder.padding(offset, T::inline_size(encoder.context)),
2625    }
2626    Ok(())
2627}
2628
2629/// Presence indicators always include at least one non-zero byte, while absence
2630/// indicators should always be entirely zeros. Like `Decode::decode`, the
2631/// caller is responsible for bounds checks.
2632#[inline]
2633fn check_for_presence<D: ResourceDialect>(
2634    decoder: &Decoder<'_, D>,
2635    offset: usize,
2636    inline_size: usize,
2637) -> bool {
2638    debug_assert!(offset + inline_size <= decoder.buf.len());
2639    let range = unsafe { decoder.buf.get_unchecked(offset..offset + inline_size) };
2640    range.iter().any(|byte| *byte != 0)
2641}
2642
2643////////////////////////////////////////////////////////////////////////////////
2644// Envelopes
2645////////////////////////////////////////////////////////////////////////////////
2646
2647#[doc(hidden)] // only exported for use in macros or generated code
2648#[inline]
2649pub unsafe fn encode_in_envelope<T: TypeMarker, D: ResourceDialect>(
2650    val: impl Encode<T, D>,
2651    encoder: &mut Encoder<'_, D>,
2652    offset: usize,
2653    mut depth: Depth,
2654) -> Result<()> {
2655    depth.increment()?;
2656    let bytes_before = encoder.buf.len();
2657    let handles_before = encoder.handles.len();
2658    let inline_size = T::inline_size(encoder.context);
2659    if inline_size <= 4 {
2660        // Zero out the 4 byte inlined region and set the flag at the same time.
2661        encoder.write_num(1u64 << 48, offset);
2662        val.encode(encoder, offset, depth)?;
2663        let handles_written = (encoder.handles.len() - handles_before) as u16;
2664        encoder.write_num(handles_written, offset + 4);
2665    } else {
2666        let out_of_line_offset = encoder.out_of_line_offset(inline_size);
2667        val.encode(encoder, out_of_line_offset, depth)?;
2668        let bytes_written = (encoder.buf.len() - bytes_before) as u32;
2669        let handles_written = (encoder.handles.len() - handles_before) as u32;
2670        debug_assert_eq!(bytes_written % 8, 0);
2671        encoder.write_num(bytes_written, offset);
2672        encoder.write_num(handles_written, offset + 4);
2673    }
2674    Ok(())
2675}
2676
2677#[doc(hidden)] // only exported for use in macros or generated code
2678#[inline]
2679pub unsafe fn encode_in_envelope_optional<T: TypeMarker, D: ResourceDialect>(
2680    val: Option<impl Encode<T, D>>,
2681    encoder: &mut Encoder<'_, D>,
2682    offset: usize,
2683    depth: Depth,
2684) -> Result<()> {
2685    match val {
2686        None => encoder.write_num(0u64, offset),
2687        Some(val) => encode_in_envelope(val, encoder, offset, depth)?,
2688    }
2689    Ok(())
2690}
2691
2692/// Decodes and validates an envelope header. Returns `None` if absent and
2693/// `Some((inlined, num_bytes, num_handles))` if present.
2694#[doc(hidden)] // only exported for use in macros or generated code
2695#[inline(always)]
2696pub unsafe fn decode_envelope_header<D: ResourceDialect>(
2697    decoder: &mut Decoder<'_, D>,
2698    offset: usize,
2699) -> Result<Option<(bool, u32, u32)>> {
2700    let num_bytes = decoder.read_num::<u32>(offset);
2701    let num_handles = decoder.read_num::<u16>(offset + 4) as u32;
2702    let inlined = decoder.read_num::<u16>(offset + 6);
2703    match (num_bytes, num_handles, inlined) {
2704        (0, 0, 0) => Ok(None),
2705        (_, _, 1) => Ok(Some((true, 4, num_handles))),
2706        (_, _, 0) if num_bytes % 8 == 0 => Ok(Some((false, num_bytes, num_handles))),
2707        (_, _, 0) => Err(Error::InvalidNumBytesInEnvelope),
2708        _ => Err(Error::InvalidInlineMarkerInEnvelope),
2709    }
2710}
2711
2712/// Decodes a FIDL envelope and skips over any out-of-line bytes and handles.
2713#[doc(hidden)] // only exported for use in macros or generated code
2714#[inline]
2715pub unsafe fn decode_unknown_envelope<D: ResourceDialect>(
2716    decoder: &mut Decoder<'_, D>,
2717    offset: usize,
2718    mut depth: Depth,
2719) -> Result<()> {
2720    if let Some((inlined, num_bytes, num_handles)) = decode_envelope_header(decoder, offset)? {
2721        if !inlined {
2722            depth.increment()?;
2723            // Calling decoder.out_of_line_offset(0) is not allowed.
2724            if num_bytes != 0 {
2725                let _ = decoder.out_of_line_offset(num_bytes as usize)?;
2726            }
2727        }
2728        if num_handles != 0 {
2729            for _ in 0..num_handles {
2730                decoder.drop_next_handle()?;
2731            }
2732        }
2733    }
2734    Ok(())
2735}
2736
2737////////////////////////////////////////////////////////////////////////////////
2738// Unions
2739////////////////////////////////////////////////////////////////////////////////
2740
2741/// Decodes the inline portion of a union.
2742/// Returns `(ordinal, inlined, num_bytes, num_handles)`.
2743#[doc(hidden)] // only exported for use in macros or generated code
2744#[inline]
2745pub unsafe fn decode_union_inline_portion<D: ResourceDialect>(
2746    decoder: &mut Decoder<'_, D>,
2747    offset: usize,
2748) -> Result<(u64, bool, u32, u32)> {
2749    let ordinal = decoder.read_num::<u64>(offset);
2750    match decode_envelope_header(decoder, offset + 8)? {
2751        Some((inlined, num_bytes, num_handles)) => Ok((ordinal, inlined, num_bytes, num_handles)),
2752        None => Err(Error::NotNullable),
2753    }
2754}
2755
2756////////////////////////////////////////////////////////////////////////////////
2757// Result unions
2758////////////////////////////////////////////////////////////////////////////////
2759
2760/// The FIDL union generated for strict two-way methods with errors.
2761pub struct ResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2762
2763/// The FIDL union generated for flexible two-way methods without errors.
2764pub struct FlexibleType<T: TypeMarker>(PhantomData<T>);
2765
2766/// The FIDL union generated for flexible two-way methods with errors.
2767pub struct FlexibleResultType<T: TypeMarker, E: TypeMarker>(PhantomData<(T, E)>);
2768
2769/// Owned type for `FlexibleType`.
2770#[doc(hidden)] // only exported for use in macros or generated code
2771#[derive(Debug)]
2772pub enum Flexible<T> {
2773    Ok(T),
2774    FrameworkErr(FrameworkErr),
2775}
2776
2777/// Owned type for `FlexibleResultType`.
2778#[doc(hidden)] // only exported for use in macros or generated code
2779#[derive(Debug)]
2780pub enum FlexibleResult<T, E> {
2781    Ok(T),
2782    DomainErr(E),
2783    FrameworkErr(FrameworkErr),
2784}
2785
2786/// Internal FIDL framework error type used to identify unknown methods.
2787#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
2788#[repr(i32)]
2789pub enum FrameworkErr {
2790    /// Method was not recognized.
2791    UnknownMethod = zx_types::ZX_ERR_NOT_SUPPORTED,
2792}
2793
2794impl FrameworkErr {
2795    #[inline]
2796    fn from_primitive(prim: i32) -> Option<Self> {
2797        match prim {
2798            zx_types::ZX_ERR_NOT_SUPPORTED => Some(Self::UnknownMethod),
2799            _ => None,
2800        }
2801    }
2802
2803    #[inline(always)]
2804    const fn into_primitive(self) -> i32 {
2805        self as i32
2806    }
2807}
2808
2809unsafe impl TypeMarker for FrameworkErr {
2810    type Owned = Self;
2811    #[inline(always)]
2812    fn inline_align(_context: Context) -> usize {
2813        std::mem::align_of::<i32>()
2814    }
2815
2816    #[inline(always)]
2817    fn inline_size(_context: Context) -> usize {
2818        std::mem::size_of::<i32>()
2819    }
2820
2821    #[inline(always)]
2822    fn encode_is_copy() -> bool {
2823        true
2824    }
2825
2826    #[inline(always)]
2827    fn decode_is_copy() -> bool {
2828        false
2829    }
2830}
2831
2832impl ValueTypeMarker for FrameworkErr {
2833    type Borrowed<'a> = Self;
2834    #[inline(always)]
2835    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
2836        *value
2837    }
2838}
2839
2840unsafe impl<D: ResourceDialect> Encode<Self, D> for FrameworkErr {
2841    #[inline]
2842    unsafe fn encode(
2843        self,
2844        encoder: &mut Encoder<'_, D>,
2845        offset: usize,
2846        _depth: Depth,
2847    ) -> Result<()> {
2848        encoder.debug_check_bounds::<Self>(offset);
2849        encoder.write_num(self.into_primitive(), offset);
2850        Ok(())
2851    }
2852}
2853
2854impl<D: ResourceDialect> Decode<Self, D> for FrameworkErr {
2855    #[inline(always)]
2856    fn new_empty() -> Self {
2857        Self::UnknownMethod
2858    }
2859
2860    #[inline]
2861    unsafe fn decode(
2862        &mut self,
2863        decoder: &mut Decoder<'_, D>,
2864        offset: usize,
2865        _depth: Depth,
2866    ) -> Result<()> {
2867        decoder.debug_check_bounds::<Self>(offset);
2868        let prim = decoder.read_num::<i32>(offset);
2869        *self = Self::from_primitive(prim).ok_or(Error::InvalidEnumValue)?;
2870        Ok(())
2871    }
2872}
2873
2874impl<T> Flexible<T> {
2875    /// Creates a new instance from the underlying value.
2876    pub fn new(value: T) -> Self {
2877        Self::Ok(value)
2878    }
2879
2880    /// Converts to a `fidl::Result`, mapping framework errors to `fidl::Error`.
2881    pub fn into_result<P: ProtocolMarker>(self, method_name: &'static str) -> Result<T> {
2882        match self {
2883            Flexible::Ok(ok) => Ok(ok),
2884            Flexible::FrameworkErr(FrameworkErr::UnknownMethod) => {
2885                Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2886            }
2887        }
2888    }
2889}
2890
2891impl<T, E> FlexibleResult<T, E> {
2892    /// Creates a new instance from an `std::result::Result`.
2893    pub fn new(result: std::result::Result<T, E>) -> Self {
2894        match result {
2895            Ok(value) => Self::Ok(value),
2896            Err(err) => Self::DomainErr(err),
2897        }
2898    }
2899
2900    /// Converts to a `fidl::Result`, mapping framework errors to `fidl::Error`.
2901    pub fn into_result<P: ProtocolMarker>(
2902        self,
2903        method_name: &'static str,
2904    ) -> Result<std::result::Result<T, E>> {
2905        match self {
2906            FlexibleResult::Ok(ok) => Ok(Ok(ok)),
2907            FlexibleResult::DomainErr(err) => Ok(Err(err)),
2908            FlexibleResult::FrameworkErr(FrameworkErr::UnknownMethod) => {
2909                Err(Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
2910            }
2911        }
2912    }
2913}
2914
2915/// Implements `TypeMarker`, `Encode`, and `Decode` for a result union type.
2916macro_rules! impl_result_union {
2917    (
2918        params: [$($encode_param:ident: Encode<$type_param:ident>),*],
2919        ty: $ty:ty,
2920        owned: $owned:ty,
2921        encode: $encode:ty,
2922        members: [$(
2923            {
2924                ctor: { $($member_ctor:tt)* },
2925                ty: $member_ty:ty,
2926                ordinal: $member_ordinal:tt,
2927            },
2928        )*]
2929    ) => {
2930        unsafe impl<$($type_param: TypeMarker),*> TypeMarker for $ty {
2931            type Owned = $owned;
2932
2933            #[inline(always)]
2934            fn inline_align(_context: Context) -> usize {
2935                8
2936            }
2937
2938            #[inline(always)]
2939            fn inline_size(_context: Context) -> usize {
2940                16
2941            }
2942        }
2943
2944        unsafe impl<D: ResourceDialect, $($type_param: TypeMarker, $encode_param: Encode<$type_param, D>),*> Encode<$ty, D> for $encode {
2945            #[inline]
2946            unsafe fn encode(self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth) -> Result<()> {
2947                encoder.debug_check_bounds::<$ty>(offset);
2948                match self {
2949                    $(
2950                        $($member_ctor)*(val) => {
2951                            encoder.write_num::<u64>($member_ordinal, offset);
2952                            encode_in_envelope::<$member_ty, D>(val, encoder, offset + 8, depth)
2953                        }
2954                    )*
2955                }
2956            }
2957        }
2958
2959        impl<D: ResourceDialect, $($type_param: TypeMarker),*> Decode<$ty, D> for $owned
2960        where $($type_param::Owned: Decode<$type_param, D>),*
2961        {
2962            #[inline(always)]
2963            fn new_empty() -> Self {
2964                #![allow(unreachable_code)]
2965                $(
2966                    return $($member_ctor)*(new_empty!($member_ty, D));
2967                )*
2968            }
2969
2970            #[inline]
2971            unsafe fn decode(&mut self, decoder: &mut Decoder<'_, D>, offset: usize, mut depth: Depth) -> Result<()> {
2972                decoder.debug_check_bounds::<$ty>(offset);
2973                let next_out_of_line = decoder.next_out_of_line();
2974                let handles_before = decoder.remaining_handles();
2975                let (ordinal, inlined, num_bytes, num_handles) = decode_union_inline_portion(decoder, offset)?;
2976                let member_inline_size = match ordinal {
2977                    $(
2978                        $member_ordinal => <$member_ty as TypeMarker>::inline_size(decoder.context),
2979                    )*
2980                    _ => return Err(Error::UnknownUnionTag),
2981                };
2982                if inlined != (member_inline_size <= 4) {
2983                    return Err(Error::InvalidInlineBitInEnvelope);
2984                }
2985                let inner_offset;
2986                if inlined {
2987                    decoder.check_inline_envelope_padding(offset + 8, member_inline_size)?;
2988                    inner_offset = offset + 8;
2989                } else {
2990                    depth.increment()?;
2991                    inner_offset = decoder.out_of_line_offset(member_inline_size)?;
2992                }
2993                match ordinal {
2994                    $(
2995                        $member_ordinal => {
2996                            #[allow(irrefutable_let_patterns)]
2997                            if let $($member_ctor)*(_) = self {
2998                                // Do nothing, read the value into the object
2999                            } else {
3000                                // Initialize `self` to the right variant
3001                                *self = $($member_ctor)*(new_empty!($member_ty, D));
3002                            }
3003                            #[allow(irrefutable_let_patterns)]
3004                            if let $($member_ctor)*(ref mut val) = self {
3005                                decode!($member_ty, D, val, decoder, inner_offset, depth)?;
3006                            } else {
3007                                unreachable!()
3008                            }
3009                        }
3010                    )*
3011                    ordinal => panic!("unexpected ordinal {:?}", ordinal)
3012                }
3013                if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize) {
3014                    return Err(Error::InvalidNumBytesInEnvelope);
3015                }
3016                if handles_before != decoder.remaining_handles() + (num_handles as usize) {
3017                    return Err(Error::InvalidNumHandlesInEnvelope);
3018                }
3019                Ok(())
3020            }
3021        }
3022    };
3023}
3024
3025impl_result_union! {
3026    params: [X: Encode<T>, Y: Encode<E>],
3027    ty: ResultType<T, E>,
3028    owned: std::result::Result<T::Owned, E::Owned>,
3029    encode: std::result::Result<X, Y>,
3030    members: [
3031        { ctor: { Ok }, ty: T, ordinal: 1, },
3032        { ctor: { Err }, ty: E, ordinal: 2, },
3033    ]
3034}
3035
3036impl_result_union! {
3037    params: [X: Encode<T>],
3038    ty: FlexibleType<T>,
3039    owned: Flexible<T::Owned>,
3040    encode: Flexible<X>,
3041    members: [
3042        { ctor: { Flexible::Ok }, ty: T, ordinal: 1, },
3043        { ctor: { Flexible::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3044    ]
3045}
3046
3047impl_result_union! {
3048    params: [X: Encode<T>, Y: Encode<E>],
3049    ty: FlexibleResultType<T, E>,
3050    owned: FlexibleResult<T::Owned, E::Owned>,
3051    encode: FlexibleResult<X, Y>,
3052    members: [
3053        { ctor: { FlexibleResult::Ok }, ty: T, ordinal: 1, },
3054        { ctor: { FlexibleResult::DomainErr }, ty: E, ordinal: 2, },
3055        { ctor: { FlexibleResult::FrameworkErr }, ty: FrameworkErr, ordinal: 3, },
3056    ]
3057}
3058
3059////////////////////////////////////////////////////////////////////////////////
3060// Epitaphs
3061////////////////////////////////////////////////////////////////////////////////
3062
3063/// The body of a FIDL Epitaph
3064#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3065pub struct EpitaphBody {
3066    /// The error status.
3067    pub error: zx_status::Status,
3068}
3069
3070unsafe impl TypeMarker for EpitaphBody {
3071    type Owned = Self;
3072
3073    #[inline(always)]
3074    fn inline_align(_context: Context) -> usize {
3075        4
3076    }
3077
3078    #[inline(always)]
3079    fn inline_size(_context: Context) -> usize {
3080        4
3081    }
3082}
3083
3084impl ValueTypeMarker for EpitaphBody {
3085    type Borrowed<'a> = &'a Self;
3086
3087    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3088        value
3089    }
3090}
3091
3092unsafe impl<D: ResourceDialect> Encode<EpitaphBody, D> for &EpitaphBody {
3093    #[inline]
3094    unsafe fn encode(
3095        self,
3096        encoder: &mut Encoder<'_, D>,
3097        offset: usize,
3098        _depth: Depth,
3099    ) -> Result<()> {
3100        encoder.debug_check_bounds::<EpitaphBody>(offset);
3101        encoder.write_num::<i32>(self.error.into_raw(), offset);
3102        Ok(())
3103    }
3104}
3105
3106impl<D: ResourceDialect> Decode<Self, D> for EpitaphBody {
3107    #[inline(always)]
3108    fn new_empty() -> Self {
3109        Self { error: zx_status::Status::from_raw(0) }
3110    }
3111
3112    #[inline]
3113    unsafe fn decode(
3114        &mut self,
3115        decoder: &mut Decoder<'_, D>,
3116        offset: usize,
3117        _depth: Depth,
3118    ) -> Result<()> {
3119        decoder.debug_check_bounds::<Self>(offset);
3120        self.error = zx_status::Status::from_raw(decoder.read_num::<i32>(offset));
3121        Ok(())
3122    }
3123}
3124
3125////////////////////////////////////////////////////////////////////////////////
3126// Zircon types
3127////////////////////////////////////////////////////////////////////////////////
3128
3129unsafe impl TypeMarker for ObjectType {
3130    type Owned = Self;
3131
3132    #[inline(always)]
3133    fn inline_align(_context: Context) -> usize {
3134        mem::align_of::<Self>()
3135    }
3136
3137    #[inline(always)]
3138    fn inline_size(_context: Context) -> usize {
3139        mem::size_of::<Self>()
3140    }
3141}
3142
3143impl ValueTypeMarker for ObjectType {
3144    type Borrowed<'a> = Self;
3145
3146    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3147        *value
3148    }
3149}
3150
3151unsafe impl<D: ResourceDialect> Encode<ObjectType, D> for ObjectType {
3152    #[inline]
3153    unsafe fn encode(
3154        self,
3155        encoder: &mut Encoder<'_, D>,
3156        offset: usize,
3157        _depth: Depth,
3158    ) -> Result<()> {
3159        encoder.debug_check_bounds::<Self>(offset);
3160        encoder.write_num(self.into_raw(), offset);
3161        Ok(())
3162    }
3163}
3164
3165impl<D: ResourceDialect> Decode<Self, D> for ObjectType {
3166    #[inline(always)]
3167    fn new_empty() -> Self {
3168        ObjectType::NONE
3169    }
3170
3171    #[inline]
3172    unsafe fn decode(
3173        &mut self,
3174        decoder: &mut Decoder<'_, D>,
3175        offset: usize,
3176        _depth: Depth,
3177    ) -> Result<()> {
3178        decoder.debug_check_bounds::<Self>(offset);
3179        *self = Self::from_raw(decoder.read_num(offset));
3180        Ok(())
3181    }
3182}
3183
3184unsafe impl TypeMarker for Rights {
3185    type Owned = Self;
3186
3187    #[inline(always)]
3188    fn inline_align(_context: Context) -> usize {
3189        mem::align_of::<Self>()
3190    }
3191
3192    #[inline(always)]
3193    fn inline_size(_context: Context) -> usize {
3194        mem::size_of::<Self>()
3195    }
3196}
3197
3198impl ValueTypeMarker for Rights {
3199    type Borrowed<'a> = Self;
3200
3201    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3202        *value
3203    }
3204}
3205
3206unsafe impl<D: ResourceDialect> Encode<Rights, D> for Rights {
3207    #[inline]
3208    unsafe fn encode(
3209        self,
3210        encoder: &mut Encoder<'_, D>,
3211        offset: usize,
3212        _depth: Depth,
3213    ) -> Result<()> {
3214        encoder.debug_check_bounds::<Self>(offset);
3215        if self.bits() & Self::all().bits() != self.bits() {
3216            return Err(Error::InvalidBitsValue);
3217        }
3218        encoder.write_num(self.bits(), offset);
3219        Ok(())
3220    }
3221}
3222
3223impl<D: ResourceDialect> Decode<Self, D> for Rights {
3224    #[inline(always)]
3225    fn new_empty() -> Self {
3226        Rights::empty()
3227    }
3228
3229    #[inline]
3230    unsafe fn decode(
3231        &mut self,
3232        decoder: &mut Decoder<'_, D>,
3233        offset: usize,
3234        _depth: Depth,
3235    ) -> Result<()> {
3236        decoder.debug_check_bounds::<Self>(offset);
3237        *self = Self::from_bits(decoder.read_num(offset)).ok_or(Error::InvalidBitsValue)?;
3238        Ok(())
3239    }
3240}
3241
3242////////////////////////////////////////////////////////////////////////////////
3243// Messages
3244////////////////////////////////////////////////////////////////////////////////
3245
3246/// The FIDL type for a message consisting of a header `H` and body `T`.
3247pub struct GenericMessageType<H: ValueTypeMarker, T: TypeMarker>(PhantomData<(H, T)>);
3248
3249/// A struct which encodes as `GenericMessageType<H, T>` where `E: Encode<T>`.
3250pub struct GenericMessage<H, E> {
3251    /// Header of the message.
3252    pub header: H,
3253    /// Body of the message.
3254    pub body: E,
3255}
3256
3257/// The owned type for `GenericMessageType`.
3258///
3259/// Uninhabited because we never decode full messages. We decode the header and
3260/// body separately, as we usually we don't know the body's type until after
3261/// we've decoded the header.
3262pub enum GenericMessageOwned {}
3263
3264unsafe impl<H: ValueTypeMarker, T: TypeMarker> TypeMarker for GenericMessageType<H, T> {
3265    type Owned = GenericMessageOwned;
3266
3267    #[inline(always)]
3268    fn inline_align(context: Context) -> usize {
3269        std::cmp::max(H::inline_align(context), T::inline_align(context))
3270    }
3271
3272    #[inline(always)]
3273    fn inline_size(context: Context) -> usize {
3274        H::inline_size(context) + T::inline_size(context)
3275    }
3276}
3277
3278unsafe impl<H: ValueTypeMarker, T: TypeMarker, E: Encode<T, D>, D: ResourceDialect>
3279    Encode<GenericMessageType<H, T>, D> for GenericMessage<<H as TypeMarker>::Owned, E>
3280where
3281    for<'a> H::Borrowed<'a>: Encode<H, D>,
3282{
3283    #[inline]
3284    unsafe fn encode(
3285        self,
3286        encoder: &mut Encoder<'_, D>,
3287        offset: usize,
3288        depth: Depth,
3289    ) -> Result<()> {
3290        encoder.debug_check_bounds::<GenericMessageType<H, T>>(offset);
3291        H::borrow(&self.header).encode(encoder, offset, depth)?;
3292        self.body.encode(encoder, offset + H::inline_size(encoder.context), depth)
3293    }
3294}
3295
3296impl<H: ValueTypeMarker, T: TypeMarker, D: ResourceDialect> Decode<GenericMessageType<H, T>, D>
3297    for GenericMessageOwned
3298{
3299    fn new_empty() -> Self {
3300        panic!("cannot create GenericMessageOwned");
3301    }
3302
3303    unsafe fn decode(
3304        &mut self,
3305        _decoder: &mut Decoder<'_, D>,
3306        _offset: usize,
3307        _depth: Depth,
3308    ) -> Result<()> {
3309        match *self {}
3310    }
3311}
3312
3313////////////////////////////////////////////////////////////////////////////////
3314// Transaction messages
3315////////////////////////////////////////////////////////////////////////////////
3316
3317/// The FIDL type for a transaction message with body `T`.
3318pub type TransactionMessageType<T> = GenericMessageType<TransactionHeader, T>;
3319
3320/// A struct which encodes as `TransactionMessageType<T>` where `E: Encode<T>`.
3321pub type TransactionMessage<E> = GenericMessage<TransactionHeader, E>;
3322
3323/// Header for transactional FIDL messages
3324#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3325#[repr(C)]
3326pub struct TransactionHeader {
3327    /// Transaction ID which identifies a request-response pair
3328    pub tx_id: u32,
3329    /// Flags set for this message. MUST NOT be validated by bindings. Usually
3330    /// temporarily during migrations.
3331    pub at_rest_flags: [u8; 2],
3332    /// Flags used for dynamically interpreting the request if it is unknown to
3333    /// the receiver.
3334    pub dynamic_flags: u8,
3335    /// Magic number indicating the message's wire format. Two sides with
3336    /// different magic numbers are incompatible with each other.
3337    pub magic_number: u8,
3338    /// Ordinal which identifies the FIDL method
3339    pub ordinal: u64,
3340}
3341
3342impl TransactionHeader {
3343    /// Returns whether the message containing this TransactionHeader is in a
3344    /// compatible wire format
3345    #[inline]
3346    pub fn is_compatible(&self) -> bool {
3347        self.magic_number == MAGIC_NUMBER_INITIAL
3348    }
3349}
3350
3351bitflags! {
3352    /// Bitflags type for transaction header at-rest flags.
3353    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3354    pub struct AtRestFlags: u16 {
3355        /// Indicates that the V2 wire format should be used instead of the V1
3356        /// wire format.
3357        /// This includes the following RFCs:
3358        /// - Efficient envelopes
3359        /// - Inlining small values in FIDL envelopes
3360        const USE_V2_WIRE_FORMAT = 2;
3361    }
3362}
3363
3364bitflags! {
3365    /// Bitflags type to flags that aid in dynamically identifying features of
3366    /// the request.
3367    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3368    pub struct DynamicFlags: u8 {
3369        /// Indicates that the request is for a flexible method.
3370        const FLEXIBLE = 1 << 7;
3371    }
3372}
3373
3374impl From<AtRestFlags> for [u8; 2] {
3375    #[inline]
3376    fn from(value: AtRestFlags) -> Self {
3377        value.bits().to_le_bytes()
3378    }
3379}
3380
3381impl TransactionHeader {
3382    /// Creates a new transaction header with the default encode context and magic number.
3383    #[inline]
3384    pub fn new(tx_id: u32, ordinal: u64, dynamic_flags: DynamicFlags) -> Self {
3385        TransactionHeader::new_full(
3386            tx_id,
3387            ordinal,
3388            default_encode_context(),
3389            dynamic_flags,
3390            MAGIC_NUMBER_INITIAL,
3391        )
3392    }
3393
3394    /// Creates a new transaction header with a specific context and magic number.
3395    #[inline]
3396    pub fn new_full(
3397        tx_id: u32,
3398        ordinal: u64,
3399        context: Context,
3400        dynamic_flags: DynamicFlags,
3401        magic_number: u8,
3402    ) -> Self {
3403        TransactionHeader {
3404            tx_id,
3405            at_rest_flags: context.at_rest_flags().into(),
3406            dynamic_flags: dynamic_flags.bits(),
3407            magic_number,
3408            ordinal,
3409        }
3410    }
3411
3412    /// Returns true if the header is for an epitaph message.
3413    #[inline]
3414    pub fn is_epitaph(&self) -> bool {
3415        self.ordinal == EPITAPH_ORDINAL
3416    }
3417
3418    /// Returns an error if this header has an incompatible wire format.
3419    #[inline]
3420    pub fn validate_wire_format(&self) -> Result<()> {
3421        if self.magic_number != MAGIC_NUMBER_INITIAL {
3422            return Err(Error::IncompatibleMagicNumber(self.magic_number));
3423        }
3424        if !self.at_rest_flags().contains(AtRestFlags::USE_V2_WIRE_FORMAT) {
3425            return Err(Error::UnsupportedWireFormatVersion);
3426        }
3427        Ok(())
3428    }
3429
3430    /// Returns an error if this request header has an incorrect transaction id
3431    /// for the given method type.
3432    #[inline]
3433    pub fn validate_request_tx_id(&self, method_type: MethodType) -> Result<()> {
3434        match method_type {
3435            MethodType::OneWay if self.tx_id != 0 => Err(Error::InvalidRequestTxid),
3436            MethodType::TwoWay if self.tx_id == 0 => Err(Error::InvalidRequestTxid),
3437            _ => Ok(()),
3438        }
3439    }
3440
3441    /// Returns the header's migration flags as a `AtRestFlags` value.
3442    #[inline]
3443    pub fn at_rest_flags(&self) -> AtRestFlags {
3444        AtRestFlags::from_bits_truncate(u16::from_le_bytes(self.at_rest_flags))
3445    }
3446
3447    /// Returns the header's dynamic flags as a `DynamicFlags` value.
3448    #[inline]
3449    pub fn dynamic_flags(&self) -> DynamicFlags {
3450        DynamicFlags::from_bits_truncate(self.dynamic_flags)
3451    }
3452
3453    /// Returns the context to use for decoding the message body associated with
3454    /// this header. During migrations, this is dependent on `self.flags()` and
3455    /// controls dynamic behavior in the read path.
3456    #[inline]
3457    pub fn decoding_context(&self) -> Context {
3458        Context { wire_format_version: WireFormatVersion::V2 }
3459    }
3460}
3461
3462/// Decodes the transaction header from a message.
3463/// Returns the header and a reference to the tail of the message.
3464pub fn decode_transaction_header(bytes: &[u8]) -> Result<(TransactionHeader, &[u8])> {
3465    let mut header = new_empty!(TransactionHeader, NoHandleResourceDialect);
3466    let context = Context { wire_format_version: WireFormatVersion::V2 };
3467    let header_len = <TransactionHeader as TypeMarker>::inline_size(context);
3468    if bytes.len() < header_len {
3469        return Err(Error::OutOfRange);
3470    }
3471    let (header_bytes, body_bytes) = bytes.split_at(header_len);
3472    Decoder::<NoHandleResourceDialect>::decode_with_context::<TransactionHeader>(
3473        context,
3474        header_bytes,
3475        &mut [],
3476        &mut header,
3477    )
3478    .map_err(|_| Error::InvalidHeader)?;
3479    header.validate_wire_format()?;
3480    Ok((header, body_bytes))
3481}
3482
3483unsafe impl TypeMarker for TransactionHeader {
3484    type Owned = Self;
3485
3486    #[inline(always)]
3487    fn inline_align(_context: Context) -> usize {
3488        8
3489    }
3490
3491    #[inline(always)]
3492    fn inline_size(_context: Context) -> usize {
3493        16
3494    }
3495}
3496
3497impl ValueTypeMarker for TransactionHeader {
3498    type Borrowed<'a> = &'a Self;
3499
3500    fn borrow(value: &Self::Owned) -> Self::Borrowed<'_> {
3501        value
3502    }
3503}
3504
3505unsafe impl<D: ResourceDialect> Encode<TransactionHeader, D> for &TransactionHeader {
3506    #[inline]
3507    unsafe fn encode(
3508        self,
3509        encoder: &mut Encoder<'_, D>,
3510        offset: usize,
3511        _depth: Depth,
3512    ) -> Result<()> {
3513        encoder.debug_check_bounds::<TransactionHeader>(offset);
3514        unsafe {
3515            let buf_ptr = encoder.buf.as_mut_ptr().add(offset);
3516            (buf_ptr as *mut TransactionHeader).write_unaligned(*self);
3517        }
3518        Ok(())
3519    }
3520}
3521
3522impl<D: ResourceDialect> Decode<Self, D> for TransactionHeader {
3523    #[inline(always)]
3524    fn new_empty() -> Self {
3525        Self { tx_id: 0, at_rest_flags: [0; 2], dynamic_flags: 0, magic_number: 0, ordinal: 0 }
3526    }
3527
3528    #[inline]
3529    unsafe fn decode(
3530        &mut self,
3531        decoder: &mut Decoder<'_, D>,
3532        offset: usize,
3533        _depth: Depth,
3534    ) -> Result<()> {
3535        decoder.debug_check_bounds::<Self>(offset);
3536        unsafe {
3537            let buf_ptr = decoder.buf.as_ptr().add(offset);
3538            let obj_ptr = self as *mut TransactionHeader;
3539            std::ptr::copy_nonoverlapping(buf_ptr, obj_ptr as *mut u8, 16);
3540        }
3541        Ok(())
3542    }
3543}
3544
3545////////////////////////////////////////////////////////////////////////////////
3546// TLS buffer
3547////////////////////////////////////////////////////////////////////////////////
3548
3549/// Thread-local buffer for encoding and decoding FIDL transactions. Needed to
3550/// implement `ResourceDialect`.
3551pub struct TlsBuf<D: ResourceDialect> {
3552    bytes: Vec<u8>,
3553    encode_handles: Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3554    decode_handles: Vec<<D::Handle as HandleFor<D>>::HandleInfo>,
3555}
3556
3557impl<D: ResourceDialect> Default for TlsBuf<D> {
3558    /// Create a new `TlsBuf`
3559    fn default() -> TlsBuf<D> {
3560        TlsBuf {
3561            bytes: Vec::with_capacity(MIN_BUF_BYTES_SIZE),
3562            encode_handles: Vec::new(),
3563            decode_handles: Vec::new(),
3564        }
3565    }
3566}
3567
3568#[inline]
3569fn with_tls_buf<D: ResourceDialect, R>(f: impl FnOnce(&mut TlsBuf<D>) -> R) -> R {
3570    D::with_tls_buf(f)
3571}
3572
3573pub(crate) const MIN_BUF_BYTES_SIZE: usize = 512;
3574
3575/// Acquire a mutable reference to the thread-local buffers used for encoding.
3576///
3577/// This function may not be called recursively.
3578#[inline]
3579pub fn with_tls_encode_buf<R, D: ResourceDialect>(
3580    f: impl FnOnce(
3581        &mut Vec<u8>,
3582        &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3583    ) -> R,
3584) -> R {
3585    with_tls_buf::<D, R>(|buf| {
3586        let res = f(&mut buf.bytes, &mut buf.encode_handles);
3587        buf.bytes.clear();
3588        buf.encode_handles.clear();
3589        res
3590    })
3591}
3592
3593/// Acquire a mutable reference to the thread-local buffers used for decoding.
3594///
3595/// This function may not be called recursively.
3596#[inline]
3597pub fn with_tls_decode_buf<R, D: ResourceDialect>(
3598    f: impl FnOnce(&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>) -> R,
3599) -> R {
3600    with_tls_buf::<D, R>(|buf| {
3601        let res = f(&mut buf.bytes, &mut buf.decode_handles);
3602        buf.bytes.clear();
3603        buf.decode_handles.clear();
3604        res
3605    })
3606}
3607
3608/// Encodes the provided type into the thread-local encoding buffers.
3609///
3610/// This function may not be called recursively.
3611#[inline]
3612pub fn with_tls_encoded<T: TypeMarker, D: ResourceDialect, Out>(
3613    val: impl Encode<T, D>,
3614    f: impl FnOnce(
3615        &mut Vec<u8>,
3616        &mut Vec<<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition>,
3617    ) -> Result<Out>,
3618) -> Result<Out> {
3619    with_tls_encode_buf::<Result<Out>, D>(|bytes, handles| {
3620        Encoder::<D>::encode(bytes, handles, val)?;
3621        f(bytes, handles)
3622    })
3623}
3624
3625////////////////////////////////////////////////////////////////////////////////
3626// Tests
3627////////////////////////////////////////////////////////////////////////////////
3628
3629#[cfg(test)]
3630mod test {
3631    // Silence dead code errors from unused functions produced by macros like
3632    // `fidl_bits!`, `fidl_union!`, etc. To the compiler, it's as if we defined
3633    // a pub fn in a private mod and never used it. Unfortunately placing this
3634    // attribute directly on the macro invocations does not work.
3635    #![allow(dead_code)]
3636
3637    use super::*;
3638    use crate::handle::{convert_handle_dispositions_to_infos, AsHandleRef};
3639    use crate::time::{BootInstant, BootTicks, MonotonicInstant, MonotonicTicks};
3640    use assert_matches::assert_matches;
3641    use std::fmt;
3642
3643    const CONTEXTS: [Context; 1] = [Context { wire_format_version: WireFormatVersion::V2 }];
3644
3645    const OBJECT_TYPE_NONE: u32 = crate::handle::ObjectType::NONE.into_raw();
3646    const SAME_RIGHTS: u32 = crate::handle::Rights::SAME_RIGHTS.bits();
3647
3648    #[track_caller]
3649    fn to_infos(dispositions: &mut Vec<HandleDisposition<'_>>) -> Vec<HandleInfo> {
3650        convert_handle_dispositions_to_infos(mem::take(dispositions)).unwrap()
3651    }
3652
3653    #[track_caller]
3654    pub fn encode_decode<T: TypeMarker>(
3655        ctx: Context,
3656        start: impl Encode<T, DefaultFuchsiaResourceDialect>,
3657    ) -> T::Owned
3658    where
3659        T::Owned: Decode<T, DefaultFuchsiaResourceDialect>,
3660    {
3661        let buf = &mut Vec::new();
3662        let handle_buf = &mut Vec::new();
3663        Encoder::encode_with_context::<T>(ctx, buf, handle_buf, start).expect("Encoding failed");
3664        let mut out = T::Owned::new_empty();
3665        Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
3666            ctx,
3667            buf,
3668            &mut to_infos(handle_buf),
3669            &mut out,
3670        )
3671        .expect("Decoding failed");
3672        out
3673    }
3674
3675    #[track_caller]
3676    fn encode_assert_bytes<T: TypeMarker>(
3677        ctx: Context,
3678        data: impl Encode<T, DefaultFuchsiaResourceDialect>,
3679        encoded_bytes: &[u8],
3680    ) {
3681        let buf = &mut Vec::new();
3682        let handle_buf = &mut Vec::new();
3683        Encoder::encode_with_context::<T>(ctx, buf, handle_buf, data).expect("Encoding failed");
3684        assert_eq!(buf, encoded_bytes);
3685    }
3686
3687    #[track_caller]
3688    fn identity<T>(data: &T::Owned)
3689    where
3690        T: ValueTypeMarker,
3691        T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3692        for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3693    {
3694        for ctx in CONTEXTS {
3695            assert_eq!(*data, encode_decode(ctx, T::borrow(data)));
3696        }
3697    }
3698
3699    #[track_caller]
3700    fn identities<T>(values: &[T::Owned])
3701    where
3702        T: ValueTypeMarker,
3703        T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3704        for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3705    {
3706        for value in values {
3707            identity::<T>(value);
3708        }
3709    }
3710
3711    #[test]
3712    fn encode_decode_byte() {
3713        identities::<u8>(&[0u8, 57u8, 255u8]);
3714        identities::<i8>(&[0i8, -57i8, 12i8]);
3715        identity::<Optional<Vector<i32, 3>>>(&None::<Vec<i32>>);
3716    }
3717
3718    #[test]
3719    fn encode_decode_multibyte() {
3720        identities::<u64>(&[0u64, 1u64, u64::MAX, u64::MIN]);
3721        identities::<i64>(&[0i64, 1i64, i64::MAX, i64::MIN]);
3722        identities::<f32>(&[0f32, 1f32, f32::MAX, f32::MIN]);
3723        identities::<f64>(&[0f64, 1f64, f64::MAX, f64::MIN]);
3724    }
3725
3726    #[test]
3727    fn encode_decode_nan() {
3728        for ctx in CONTEXTS {
3729            assert!(encode_decode::<f32>(ctx, f32::NAN).is_nan());
3730            assert!(encode_decode::<f64>(ctx, f64::NAN).is_nan());
3731        }
3732    }
3733
3734    #[test]
3735    fn encode_decode_instants() {
3736        let monotonic = MonotonicInstant::from_nanos(987654321);
3737        let boot = BootInstant::from_nanos(987654321);
3738        let monotonic_ticks = MonotonicTicks::from_raw(111111111);
3739        let boot_ticks = BootTicks::from_raw(22222222);
3740        for ctx in CONTEXTS {
3741            assert_eq!(encode_decode::<BootInstant>(ctx, boot), boot);
3742            assert_eq!(encode_decode::<MonotonicInstant>(ctx, monotonic), monotonic);
3743            assert_eq!(encode_decode::<BootTicks>(ctx, boot_ticks), boot_ticks);
3744            assert_eq!(encode_decode::<MonotonicTicks>(ctx, monotonic_ticks), monotonic_ticks);
3745        }
3746    }
3747
3748    #[test]
3749    fn encode_decode_out_of_line() {
3750        type V<T> = UnboundedVector<T>;
3751        type S = UnboundedString;
3752        type O<T> = Optional<T>;
3753
3754        identity::<V<i32>>(&Vec::<i32>::new());
3755        identity::<V<i32>>(&vec![1, 2, 3]);
3756        identity::<O<V<i32>>>(&None::<Vec<i32>>);
3757        identity::<O<V<i32>>>(&Some(Vec::<i32>::new()));
3758        identity::<O<V<i32>>>(&Some(vec![1, 2, 3]));
3759        identity::<O<V<V<i32>>>>(&Some(vec![vec![1, 2, 3]]));
3760        identity::<O<V<O<V<i32>>>>>(&Some(vec![Some(vec![1, 2, 3])]));
3761        identity::<S>(&"".to_string());
3762        identity::<S>(&"foo".to_string());
3763        identity::<O<S>>(&None::<String>);
3764        identity::<O<S>>(&Some("".to_string()));
3765        identity::<O<S>>(&Some("foo".to_string()));
3766        identity::<O<V<O<S>>>>(&Some(vec![None, Some("foo".to_string())]));
3767        identity::<V<S>>(&vec!["foo".to_string(), "bar".to_string()]);
3768    }
3769
3770    #[test]
3771    fn array_of_arrays() {
3772        identity::<Array<Array<u32, 5>, 2>>(&[[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]);
3773    }
3774
3775    fn slice_identity<T>(start: &[T::Owned])
3776    where
3777        T: ValueTypeMarker,
3778        T::Owned: fmt::Debug + PartialEq + Decode<T, DefaultFuchsiaResourceDialect>,
3779        for<'a> T::Borrowed<'a>: Encode<T, DefaultFuchsiaResourceDialect>,
3780    {
3781        for ctx in CONTEXTS {
3782            let decoded = encode_decode::<UnboundedVector<T>>(ctx, start);
3783            assert_eq!(start, UnboundedVector::<T>::borrow(&decoded));
3784        }
3785    }
3786
3787    #[test]
3788    fn encode_slices_of_primitives() {
3789        slice_identity::<u8>(&[]);
3790        slice_identity::<u8>(&[0]);
3791        slice_identity::<u8>(&[1, 2, 3, 4, 5, 255]);
3792
3793        slice_identity::<i8>(&[]);
3794        slice_identity::<i8>(&[0]);
3795        slice_identity::<i8>(&[1, 2, 3, 4, 5, -128, 127]);
3796
3797        slice_identity::<u64>(&[]);
3798        slice_identity::<u64>(&[0]);
3799        slice_identity::<u64>(&[1, 2, 3, 4, 5, u64::MAX]);
3800
3801        slice_identity::<f32>(&[]);
3802        slice_identity::<f32>(&[0.0]);
3803        slice_identity::<f32>(&[1.0, 2.0, 3.0, 4.0, 5.0, f32::MIN, f32::MAX]);
3804
3805        slice_identity::<f64>(&[]);
3806        slice_identity::<f64>(&[0.0]);
3807        slice_identity::<f64>(&[1.0, 2.0, 3.0, 4.0, 5.0, f64::MIN, f64::MAX]);
3808    }
3809
3810    #[test]
3811    fn result_encode_empty_ok_value() {
3812        for ctx in CONTEXTS {
3813            // An empty response is represented by () and has zero size.
3814            encode_assert_bytes::<EmptyPayload>(ctx, (), &[]);
3815        }
3816        // But in the context of an error result type Result<(), ErrorType>, the
3817        // () in Ok(()) represents an empty struct (with size 1).
3818        encode_assert_bytes::<ResultType<EmptyStruct, i32>>(
3819            Context { wire_format_version: WireFormatVersion::V2 },
3820            Ok::<(), i32>(()),
3821            &[
3822                0x01, 0x00, 0x00, 0x00, // success ordinal
3823                0x00, 0x00, 0x00, 0x00, // success ordinal [cont.]
3824                0x00, 0x00, 0x00, 0x00, // inline value: empty struct + 3 bytes padding
3825                0x00, 0x00, 0x01, 0x00, // 0 handles, flags (inlined)
3826            ],
3827        );
3828    }
3829
3830    #[test]
3831    fn result_decode_empty_ok_value() {
3832        let mut result = Err(0);
3833        Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<ResultType<EmptyStruct, u32>>(
3834            Context { wire_format_version: WireFormatVersion::V2 },
3835            &[
3836                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // success ordinal
3837                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // empty struct inline
3838            ],
3839            &mut [],
3840            &mut result,
3841        )
3842        .expect("Decoding failed");
3843        assert_matches!(result, Ok(()));
3844    }
3845
3846    #[test]
3847    fn encode_decode_result() {
3848        type Res = ResultType<UnboundedString, u32>;
3849        for ctx in CONTEXTS {
3850            assert_eq!(encode_decode::<Res>(ctx, Ok::<&str, u32>("foo")), Ok("foo".to_string()));
3851            assert_eq!(encode_decode::<Res>(ctx, Err::<&str, u32>(5)), Err(5));
3852        }
3853    }
3854
3855    #[test]
3856    fn result_validates_num_bytes() {
3857        type Res = ResultType<u64, u64>;
3858        for ctx in CONTEXTS {
3859            for ordinal in [1, 2] {
3860                // Envelope should have num_bytes set to 8, not 16.
3861                let bytes = [
3862                    ordinal, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ordinal
3863                    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 bytes, 0 handles
3864                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // present
3865                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // number
3866                ];
3867                let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3868                assert_matches!(
3869                    Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3870                        ctx,
3871                        &bytes,
3872                        &mut [],
3873                        &mut out
3874                    ),
3875                    Err(Error::InvalidNumBytesInEnvelope)
3876                );
3877            }
3878        }
3879    }
3880
3881    #[test]
3882    fn result_validates_num_handles() {
3883        type Res = ResultType<u64, u64>;
3884        for ctx in CONTEXTS {
3885            for ordinal in [1, 2] {
3886                // Envelope should have num_handles set to 0, not 1.
3887                let bytes = [
3888                    ordinal, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ordinal
3889                    0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 16 bytes, 1 handle
3890                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // present
3891                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // number
3892                ];
3893                let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3894                assert_matches!(
3895                    Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3896                        ctx,
3897                        &bytes,
3898                        &mut [],
3899                        &mut out
3900                    ),
3901                    Err(Error::InvalidNumHandlesInEnvelope)
3902                );
3903            }
3904        }
3905    }
3906
3907    #[test]
3908    fn decode_result_unknown_tag() {
3909        type Res = ResultType<u32, u32>;
3910        let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3911
3912        let bytes: &[u8] = &[
3913            // Ordinal 3 (not known to result) ----------|
3914            0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3915            // inline value -----|  NHandles |  Flags ---|
3916            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3917        ];
3918        let handle_buf = &mut Vec::<HandleInfo>::new();
3919
3920        let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3921        let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3922            ctx, bytes, handle_buf, &mut out,
3923        );
3924        assert_matches!(res, Err(Error::UnknownUnionTag));
3925    }
3926
3927    #[test]
3928    fn decode_result_success_invalid_empty_struct() {
3929        type Res = ResultType<EmptyStruct, u32>;
3930        let ctx = Context { wire_format_version: WireFormatVersion::V2 };
3931
3932        let bytes: &[u8] = &[
3933            // Ordinal 1 (success) ----------------------|
3934            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3935            // inline value -----|  NHandles |  Flags ---|
3936            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
3937        ];
3938        let handle_buf = &mut Vec::<HandleInfo>::new();
3939
3940        let mut out = new_empty!(Res, DefaultFuchsiaResourceDialect);
3941        let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<Res>(
3942            ctx, bytes, handle_buf, &mut out,
3943        );
3944        assert_matches!(res, Err(Error::Invalid));
3945    }
3946
3947    #[test]
3948    fn encode_decode_transaction_msg() {
3949        for ctx in CONTEXTS {
3950            let header = TransactionHeader {
3951                tx_id: 4,
3952                ordinal: 6,
3953                at_rest_flags: [2, 0],
3954                dynamic_flags: 0,
3955                magic_number: 1,
3956            };
3957            type Body = UnboundedString;
3958            let body = "hello";
3959
3960            let start = TransactionMessage { header, body };
3961
3962            let buf = &mut Vec::new();
3963            let handle_buf = &mut Vec::new();
3964            Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<
3965                TransactionMessageType<Body>,
3966            >(ctx, buf, handle_buf, start)
3967            .expect("Encoding failed");
3968
3969            let (out_header, out_buf) =
3970                decode_transaction_header(buf).expect("Decoding header failed");
3971            assert_eq!(header, out_header);
3972
3973            let mut body_out = String::new();
3974            Decoder::<DefaultFuchsiaResourceDialect>::decode_into::<Body>(
3975                &header,
3976                out_buf,
3977                &mut to_infos(handle_buf),
3978                &mut body_out,
3979            )
3980            .expect("Decoding body failed");
3981            assert_eq!(body, body_out);
3982        }
3983    }
3984
3985    #[test]
3986    fn direct_encode_transaction_header_strict() {
3987        let bytes = &[
3988            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, //
3989            0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
3990        ];
3991        let header = TransactionHeader {
3992            tx_id: 4,
3993            ordinal: 6,
3994            at_rest_flags: [0; 2],
3995            dynamic_flags: DynamicFlags::empty().bits(),
3996            magic_number: 1,
3997        };
3998
3999        for ctx in CONTEXTS {
4000            encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
4001        }
4002    }
4003
4004    #[test]
4005    fn direct_decode_transaction_header_strict() {
4006        let bytes = &[
4007            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, //
4008            0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
4009        ];
4010        let header = TransactionHeader {
4011            tx_id: 4,
4012            ordinal: 6,
4013            at_rest_flags: [0; 2],
4014            dynamic_flags: DynamicFlags::empty().bits(),
4015            magic_number: 1,
4016        };
4017
4018        for ctx in CONTEXTS {
4019            let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4020            Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4021                ctx,
4022                bytes,
4023                &mut [],
4024                &mut out,
4025            )
4026            .expect("Decoding failed");
4027            assert_eq!(out, header);
4028        }
4029    }
4030
4031    #[test]
4032    fn direct_encode_transaction_header_flexible() {
4033        let bytes = &[
4034            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, //
4035            0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
4036        ];
4037        let header = TransactionHeader {
4038            tx_id: 4,
4039            ordinal: 6,
4040            at_rest_flags: [0; 2],
4041            dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4042            magic_number: 1,
4043        };
4044
4045        for ctx in CONTEXTS {
4046            encode_assert_bytes::<TransactionHeader>(ctx, &header, bytes);
4047        }
4048    }
4049
4050    #[test]
4051    fn direct_decode_transaction_header_flexible() {
4052        let bytes = &[
4053            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, //
4054            0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
4055        ];
4056        let header = TransactionHeader {
4057            tx_id: 4,
4058            ordinal: 6,
4059            at_rest_flags: [0; 2],
4060            dynamic_flags: DynamicFlags::FLEXIBLE.bits(),
4061            magic_number: 1,
4062        };
4063
4064        for ctx in CONTEXTS {
4065            let mut out = new_empty!(TransactionHeader, DefaultFuchsiaResourceDialect);
4066            Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<TransactionHeader>(
4067                ctx,
4068                bytes,
4069                &mut [],
4070                &mut out,
4071            )
4072            .expect("Decoding failed");
4073            assert_eq!(out, header);
4074        }
4075    }
4076
4077    #[test]
4078    fn extra_data_is_disallowed() {
4079        for ctx in CONTEXTS {
4080            assert_matches!(
4081                Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4082                    ctx,
4083                    &[0],
4084                    &mut [],
4085                    &mut ()
4086                ),
4087                Err(Error::ExtraBytes)
4088            );
4089            assert_matches!(
4090                Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EmptyPayload>(
4091                    ctx,
4092                    &[],
4093                    &mut [HandleInfo::new(Handle::invalid(), ObjectType::NONE, Rights::NONE,)],
4094                    &mut ()
4095                ),
4096                Err(Error::ExtraHandles)
4097            );
4098        }
4099    }
4100
4101    #[test]
4102    fn encode_default_context() {
4103        let buf = &mut Vec::new();
4104        Encoder::<DefaultFuchsiaResourceDialect>::encode::<u8>(buf, &mut Vec::new(), 1u8)
4105            .expect("Encoding failed");
4106        assert_eq!(buf, &[1u8, 0, 0, 0, 0, 0, 0, 0]);
4107    }
4108
4109    #[test]
4110    fn encode_handle() {
4111        type T = HandleType<Handle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4112        for ctx in CONTEXTS {
4113            let handle = crate::handle::Event::create().into_handle();
4114            let raw_handle = handle.raw_handle();
4115            let buf = &mut Vec::new();
4116            let handle_buf = &mut Vec::new();
4117            Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<T>(
4118                ctx, buf, handle_buf, handle,
4119            )
4120            .expect("Encoding failed");
4121
4122            assert_eq!(handle_buf.len(), 1);
4123            assert!(handle_buf[0].is_move());
4124            assert_eq!(handle_buf[0].raw_handle(), raw_handle);
4125
4126            let mut handle_out = new_empty!(T);
4127            Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4128                ctx,
4129                buf,
4130                &mut to_infos(handle_buf),
4131                &mut handle_out,
4132            )
4133            .expect("Decoding failed");
4134            assert_eq!(
4135                handle_out.raw_handle(),
4136                raw_handle,
4137                "decoded handle must match encoded handle"
4138            );
4139        }
4140    }
4141
4142    #[test]
4143    fn decode_too_few_handles() {
4144        type T = HandleType<Handle, OBJECT_TYPE_NONE, SAME_RIGHTS>;
4145        for ctx in CONTEXTS {
4146            let bytes: &[u8] = &[0xff; 8];
4147            let handle_buf = &mut Vec::new();
4148            let mut handle_out = Handle::invalid();
4149            let res = Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<T>(
4150                ctx,
4151                bytes,
4152                handle_buf,
4153                &mut handle_out,
4154            );
4155            assert_matches!(res, Err(Error::OutOfRange));
4156        }
4157    }
4158
4159    #[test]
4160    fn encode_epitaph() {
4161        for ctx in CONTEXTS {
4162            let buf = &mut Vec::new();
4163            let handle_buf = &mut Vec::new();
4164            Encoder::<DefaultFuchsiaResourceDialect>::encode_with_context::<EpitaphBody>(
4165                ctx,
4166                buf,
4167                handle_buf,
4168                &EpitaphBody { error: zx_status::Status::UNAVAILABLE },
4169            )
4170            .expect("encoding failed");
4171            assert_eq!(buf, &[0xe4, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]);
4172
4173            let mut out = new_empty!(EpitaphBody, DefaultFuchsiaResourceDialect);
4174            Decoder::<DefaultFuchsiaResourceDialect>::decode_with_context::<EpitaphBody>(
4175                ctx,
4176                buf,
4177                &mut to_infos(handle_buf),
4178                &mut out,
4179            )
4180            .expect("Decoding failed");
4181            assert_eq!(EpitaphBody { error: zx_status::Status::UNAVAILABLE }, out);
4182        }
4183    }
4184}