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