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