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