Skip to main content

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