fidl/
encoding.rs

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