fidl_fuchsia_process_lifecycle/
fidl_fuchsia_process_lifecycle.rs

1// WARNING: This file is machine generated by fidlgen.
2
3#![warn(clippy::all)]
4#![allow(unused_parens, unused_mut, unused_imports, nonstandard_style)]
5
6use bitflags::bitflags;
7use fidl::client::QueryResponseFut;
8use fidl::encoding::{MessageBufFor, ProxyChannelBox, ResourceDialect};
9use fidl::endpoints::{ControlHandle as _, Responder as _};
10pub use fidl_fuchsia_process_lifecycle__common::*;
11use futures::future::{self, MaybeDone, TryFutureExt};
12use zx_status;
13
14#[derive(Debug, Default, PartialEq)]
15pub struct LifecycleOnEscrowRequest {
16    /// Escrow the outgoing directory server endpoint. Whenever the
17    /// component is started again, this will be returned as the
18    /// `PA_DIRECTORY_REQUEST` processargs entry.
19    pub outgoing_dir: Option<fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>>,
20    /// Escrow some user defined state. Whenever the component is started
21    /// again, this will be returned as the `PA_ESCROWED_DICTIONARY`
22    /// processargs entry.
23    ///
24    /// The framework will not wait for any signals on these objects.
25    ///
26    /// ## Example
27    ///
28    /// Let's say a component needs to escrow an event pair that represents
29    /// the result of some expensive calculation. It can create a
30    /// dictionary, put the event pair inside with an appropriate key
31    /// (e.g. `"my_event_pair"`), then check for that entry on startup.
32    pub escrowed_dictionary: Option<fidl_fuchsia_component_sandbox::DictionaryRef>,
33    #[doc(hidden)]
34    pub __source_breaking: fidl::marker::SourceBreaking,
35}
36
37impl fidl::Standalone<fidl::encoding::DefaultFuchsiaResourceDialect> for LifecycleOnEscrowRequest {}
38
39#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
40pub struct LifecycleMarker;
41
42impl fidl::endpoints::ProtocolMarker for LifecycleMarker {
43    type Proxy = LifecycleProxy;
44    type RequestStream = LifecycleRequestStream;
45    #[cfg(target_os = "fuchsia")]
46    type SynchronousProxy = LifecycleSynchronousProxy;
47
48    const DEBUG_NAME: &'static str = "(anonymous) Lifecycle";
49}
50
51pub trait LifecycleProxyInterface: Send + Sync {
52    fn r#stop(&self) -> Result<(), fidl::Error>;
53}
54#[derive(Debug)]
55#[cfg(target_os = "fuchsia")]
56pub struct LifecycleSynchronousProxy {
57    client: fidl::client::sync::Client,
58}
59
60#[cfg(target_os = "fuchsia")]
61impl fidl::endpoints::SynchronousProxy for LifecycleSynchronousProxy {
62    type Proxy = LifecycleProxy;
63    type Protocol = LifecycleMarker;
64
65    fn from_channel(inner: fidl::Channel) -> Self {
66        Self::new(inner)
67    }
68
69    fn into_channel(self) -> fidl::Channel {
70        self.client.into_channel()
71    }
72
73    fn as_channel(&self) -> &fidl::Channel {
74        self.client.as_channel()
75    }
76}
77
78#[cfg(target_os = "fuchsia")]
79impl LifecycleSynchronousProxy {
80    pub fn new(channel: fidl::Channel) -> Self {
81        let protocol_name = <LifecycleMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME;
82        Self { client: fidl::client::sync::Client::new(channel, protocol_name) }
83    }
84
85    pub fn into_channel(self) -> fidl::Channel {
86        self.client.into_channel()
87    }
88
89    /// Waits until an event arrives and returns it. It is safe for other
90    /// threads to make concurrent requests while waiting for an event.
91    pub fn wait_for_event(
92        &self,
93        deadline: zx::MonotonicInstant,
94    ) -> Result<LifecycleEvent, fidl::Error> {
95        LifecycleEvent::decode(self.client.wait_for_event(deadline)?)
96    }
97
98    /// The process must clean up its state in preparation for termination, and
99    /// must close the channel hosting the `Lifecycle` protocol when it is
100    /// ready to be terminated. The process should exit after it completes its
101    /// cleanup. At the discretion of the system the process may be terminated
102    /// before it closes the `Lifecycle` channel.
103    pub fn r#stop(&self) -> Result<(), fidl::Error> {
104        self.client.send::<fidl::encoding::EmptyPayload>(
105            (),
106            0x64b176f1744c6f15,
107            fidl::encoding::DynamicFlags::empty(),
108        )
109    }
110}
111
112#[cfg(target_os = "fuchsia")]
113impl From<LifecycleSynchronousProxy> for zx::Handle {
114    fn from(value: LifecycleSynchronousProxy) -> Self {
115        value.into_channel().into()
116    }
117}
118
119#[cfg(target_os = "fuchsia")]
120impl From<fidl::Channel> for LifecycleSynchronousProxy {
121    fn from(value: fidl::Channel) -> Self {
122        Self::new(value)
123    }
124}
125
126#[cfg(target_os = "fuchsia")]
127impl fidl::endpoints::FromClient for LifecycleSynchronousProxy {
128    type Protocol = LifecycleMarker;
129
130    fn from_client(value: fidl::endpoints::ClientEnd<LifecycleMarker>) -> Self {
131        Self::new(value.into_channel())
132    }
133}
134
135#[derive(Debug, Clone)]
136pub struct LifecycleProxy {
137    client: fidl::client::Client<fidl::encoding::DefaultFuchsiaResourceDialect>,
138}
139
140impl fidl::endpoints::Proxy for LifecycleProxy {
141    type Protocol = LifecycleMarker;
142
143    fn from_channel(inner: ::fidl::AsyncChannel) -> Self {
144        Self::new(inner)
145    }
146
147    fn into_channel(self) -> Result<::fidl::AsyncChannel, Self> {
148        self.client.into_channel().map_err(|client| Self { client })
149    }
150
151    fn as_channel(&self) -> &::fidl::AsyncChannel {
152        self.client.as_channel()
153    }
154}
155
156impl LifecycleProxy {
157    /// Create a new Proxy for fuchsia.process.lifecycle/Lifecycle.
158    pub fn new(channel: ::fidl::AsyncChannel) -> Self {
159        let protocol_name = <LifecycleMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME;
160        Self { client: fidl::client::Client::new(channel, protocol_name) }
161    }
162
163    /// Get a Stream of events from the remote end of the protocol.
164    ///
165    /// # Panics
166    ///
167    /// Panics if the event stream was already taken.
168    pub fn take_event_stream(&self) -> LifecycleEventStream {
169        LifecycleEventStream { event_receiver: self.client.take_event_receiver() }
170    }
171
172    /// The process must clean up its state in preparation for termination, and
173    /// must close the channel hosting the `Lifecycle` protocol when it is
174    /// ready to be terminated. The process should exit after it completes its
175    /// cleanup. At the discretion of the system the process may be terminated
176    /// before it closes the `Lifecycle` channel.
177    pub fn r#stop(&self) -> Result<(), fidl::Error> {
178        LifecycleProxyInterface::r#stop(self)
179    }
180}
181
182impl LifecycleProxyInterface for LifecycleProxy {
183    fn r#stop(&self) -> Result<(), fidl::Error> {
184        self.client.send::<fidl::encoding::EmptyPayload>(
185            (),
186            0x64b176f1744c6f15,
187            fidl::encoding::DynamicFlags::empty(),
188        )
189    }
190}
191
192pub struct LifecycleEventStream {
193    event_receiver: fidl::client::EventReceiver<fidl::encoding::DefaultFuchsiaResourceDialect>,
194}
195
196impl std::marker::Unpin for LifecycleEventStream {}
197
198impl futures::stream::FusedStream for LifecycleEventStream {
199    fn is_terminated(&self) -> bool {
200        self.event_receiver.is_terminated()
201    }
202}
203
204impl futures::Stream for LifecycleEventStream {
205    type Item = Result<LifecycleEvent, fidl::Error>;
206
207    fn poll_next(
208        mut self: std::pin::Pin<&mut Self>,
209        cx: &mut std::task::Context<'_>,
210    ) -> std::task::Poll<Option<Self::Item>> {
211        match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
212            &mut self.event_receiver,
213            cx
214        )?) {
215            Some(buf) => std::task::Poll::Ready(Some(LifecycleEvent::decode(buf))),
216            None => std::task::Poll::Ready(None),
217        }
218    }
219}
220
221#[derive(Debug)]
222pub enum LifecycleEvent {
223    OnEscrow { payload: LifecycleOnEscrowRequest },
224}
225
226impl LifecycleEvent {
227    #[allow(irrefutable_let_patterns)]
228    pub fn into_on_escrow(self) -> Option<LifecycleOnEscrowRequest> {
229        if let LifecycleEvent::OnEscrow { payload } = self {
230            Some((payload))
231        } else {
232            None
233        }
234    }
235
236    /// Decodes a message buffer as a [`LifecycleEvent`].
237    fn decode(
238        mut buf: <fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc,
239    ) -> Result<LifecycleEvent, fidl::Error> {
240        let (bytes, _handles) = buf.split_mut();
241        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
242        debug_assert_eq!(tx_header.tx_id, 0);
243        match tx_header.ordinal {
244            0x3de9c2fcb734ed48 => {
245                let mut out = fidl::new_empty!(
246                    LifecycleOnEscrowRequest,
247                    fidl::encoding::DefaultFuchsiaResourceDialect
248                );
249                fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<LifecycleOnEscrowRequest>(&tx_header, _body_bytes, _handles, &mut out)?;
250                Ok((LifecycleEvent::OnEscrow { payload: out }))
251            }
252            _ => Err(fidl::Error::UnknownOrdinal {
253                ordinal: tx_header.ordinal,
254                protocol_name: <LifecycleMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
255            }),
256        }
257    }
258}
259
260/// A Stream of incoming requests for fuchsia.process.lifecycle/Lifecycle.
261pub struct LifecycleRequestStream {
262    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
263    is_terminated: bool,
264}
265
266impl std::marker::Unpin for LifecycleRequestStream {}
267
268impl futures::stream::FusedStream for LifecycleRequestStream {
269    fn is_terminated(&self) -> bool {
270        self.is_terminated
271    }
272}
273
274impl fidl::endpoints::RequestStream for LifecycleRequestStream {
275    type Protocol = LifecycleMarker;
276    type ControlHandle = LifecycleControlHandle;
277
278    fn from_channel(channel: ::fidl::AsyncChannel) -> Self {
279        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
280    }
281
282    fn control_handle(&self) -> Self::ControlHandle {
283        LifecycleControlHandle { inner: self.inner.clone() }
284    }
285
286    fn into_inner(
287        self,
288    ) -> (::std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>, bool)
289    {
290        (self.inner, self.is_terminated)
291    }
292
293    fn from_inner(
294        inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
295        is_terminated: bool,
296    ) -> Self {
297        Self { inner, is_terminated }
298    }
299}
300
301impl futures::Stream for LifecycleRequestStream {
302    type Item = Result<LifecycleRequest, fidl::Error>;
303
304    fn poll_next(
305        mut self: std::pin::Pin<&mut Self>,
306        cx: &mut std::task::Context<'_>,
307    ) -> std::task::Poll<Option<Self::Item>> {
308        let this = &mut *self;
309        if this.inner.check_shutdown(cx) {
310            this.is_terminated = true;
311            return std::task::Poll::Ready(None);
312        }
313        if this.is_terminated {
314            panic!("polled LifecycleRequestStream after completion");
315        }
316        fidl::encoding::with_tls_decode_buf::<_, fidl::encoding::DefaultFuchsiaResourceDialect>(
317            |bytes, handles| {
318                match this.inner.channel().read_etc(cx, bytes, handles) {
319                    std::task::Poll::Ready(Ok(())) => {}
320                    std::task::Poll::Pending => return std::task::Poll::Pending,
321                    std::task::Poll::Ready(Err(zx_status::Status::PEER_CLOSED)) => {
322                        this.is_terminated = true;
323                        return std::task::Poll::Ready(None);
324                    }
325                    std::task::Poll::Ready(Err(e)) => {
326                        return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(
327                            e.into(),
328                        ))))
329                    }
330                }
331
332                // A message has been received from the channel
333                let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
334
335                std::task::Poll::Ready(Some(match header.ordinal {
336                    0x64b176f1744c6f15 => {
337                        header.validate_request_tx_id(fidl::MethodType::OneWay)?;
338                        let mut req = fidl::new_empty!(
339                            fidl::encoding::EmptyPayload,
340                            fidl::encoding::DefaultFuchsiaResourceDialect
341                        );
342                        fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<fidl::encoding::EmptyPayload>(&header, _body_bytes, handles, &mut req)?;
343                        let control_handle = LifecycleControlHandle { inner: this.inner.clone() };
344                        Ok(LifecycleRequest::Stop { control_handle })
345                    }
346                    _ => Err(fidl::Error::UnknownOrdinal {
347                        ordinal: header.ordinal,
348                        protocol_name:
349                            <LifecycleMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
350                    }),
351                }))
352            },
353        )
354    }
355}
356
357/// A component can implement the Lifecycle protocol to be notified of lifecycle
358/// events. It can also store some state in the framework, to be redelivered to
359/// the component the next time it is started (a practice called "escrowing").
360///
361/// The ELF Runner uses this protocol to communicate lifecycle changes
362/// to the component, for more details on how it uses this protocol see:
363/// https://fuchsia.dev/fuchsia-src/concepts/components/v2/elf_runner#lifecycle
364#[derive(Debug)]
365pub enum LifecycleRequest {
366    /// The process must clean up its state in preparation for termination, and
367    /// must close the channel hosting the `Lifecycle` protocol when it is
368    /// ready to be terminated. The process should exit after it completes its
369    /// cleanup. At the discretion of the system the process may be terminated
370    /// before it closes the `Lifecycle` channel.
371    Stop { control_handle: LifecycleControlHandle },
372}
373
374impl LifecycleRequest {
375    #[allow(irrefutable_let_patterns)]
376    pub fn into_stop(self) -> Option<(LifecycleControlHandle)> {
377        if let LifecycleRequest::Stop { control_handle } = self {
378            Some((control_handle))
379        } else {
380            None
381        }
382    }
383
384    /// Name of the method defined in FIDL
385    pub fn method_name(&self) -> &'static str {
386        match *self {
387            LifecycleRequest::Stop { .. } => "stop",
388        }
389    }
390}
391
392#[derive(Debug, Clone)]
393pub struct LifecycleControlHandle {
394    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
395}
396
397impl fidl::endpoints::ControlHandle for LifecycleControlHandle {
398    fn shutdown(&self) {
399        self.inner.shutdown()
400    }
401    fn shutdown_with_epitaph(&self, status: zx_status::Status) {
402        self.inner.shutdown_with_epitaph(status)
403    }
404
405    fn is_closed(&self) -> bool {
406        self.inner.channel().is_closed()
407    }
408    fn on_closed(&self) -> fidl::OnSignalsRef<'_> {
409        self.inner.channel().on_closed()
410    }
411
412    #[cfg(target_os = "fuchsia")]
413    fn signal_peer(
414        &self,
415        clear_mask: zx::Signals,
416        set_mask: zx::Signals,
417    ) -> Result<(), zx_status::Status> {
418        use fidl::Peered;
419        self.inner.channel().signal_peer(clear_mask, set_mask)
420    }
421}
422
423impl LifecycleControlHandle {
424    pub fn send_on_escrow(&self, mut payload: LifecycleOnEscrowRequest) -> Result<(), fidl::Error> {
425        self.inner.send::<LifecycleOnEscrowRequest>(
426            &mut payload,
427            0,
428            0x3de9c2fcb734ed48,
429            fidl::encoding::DynamicFlags::empty(),
430        )
431    }
432}
433
434mod internal {
435    use super::*;
436
437    impl LifecycleOnEscrowRequest {
438        #[inline(always)]
439        fn max_ordinal_present(&self) -> u64 {
440            if let Some(_) = self.escrowed_dictionary {
441                return 2;
442            }
443            if let Some(_) = self.outgoing_dir {
444                return 1;
445            }
446            0
447        }
448    }
449
450    impl fidl::encoding::ResourceTypeMarker for LifecycleOnEscrowRequest {
451        type Borrowed<'a> = &'a mut Self;
452        fn take_or_borrow<'a>(
453            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
454        ) -> Self::Borrowed<'a> {
455            value
456        }
457    }
458
459    unsafe impl fidl::encoding::TypeMarker for LifecycleOnEscrowRequest {
460        type Owned = Self;
461
462        #[inline(always)]
463        fn inline_align(_context: fidl::encoding::Context) -> usize {
464            8
465        }
466
467        #[inline(always)]
468        fn inline_size(_context: fidl::encoding::Context) -> usize {
469            16
470        }
471    }
472
473    unsafe impl
474        fidl::encoding::Encode<
475            LifecycleOnEscrowRequest,
476            fidl::encoding::DefaultFuchsiaResourceDialect,
477        > for &mut LifecycleOnEscrowRequest
478    {
479        unsafe fn encode(
480            self,
481            encoder: &mut fidl::encoding::Encoder<
482                '_,
483                fidl::encoding::DefaultFuchsiaResourceDialect,
484            >,
485            offset: usize,
486            mut depth: fidl::encoding::Depth,
487        ) -> fidl::Result<()> {
488            encoder.debug_check_bounds::<LifecycleOnEscrowRequest>(offset);
489            // Vector header
490            let max_ordinal: u64 = self.max_ordinal_present();
491            encoder.write_num(max_ordinal, offset);
492            encoder.write_num(fidl::encoding::ALLOC_PRESENT_U64, offset + 8);
493            // Calling encoder.out_of_line_offset(0) is not allowed.
494            if max_ordinal == 0 {
495                return Ok(());
496            }
497            depth.increment()?;
498            let envelope_size = 8;
499            let bytes_len = max_ordinal as usize * envelope_size;
500            #[allow(unused_variables)]
501            let offset = encoder.out_of_line_offset(bytes_len);
502            let mut _prev_end_offset: usize = 0;
503            if 1 > max_ordinal {
504                return Ok(());
505            }
506
507            // Write at offset+(ordinal-1)*envelope_size, since ordinals are one-based and envelopes
508            // are envelope_size bytes.
509            let cur_offset: usize = (1 - 1) * envelope_size;
510
511            // Zero reserved fields.
512            encoder.padding(offset + _prev_end_offset, cur_offset - _prev_end_offset);
513
514            // Safety:
515            // - bytes_len is calculated to fit envelope_size*max(member.ordinal).
516            // - Since cur_offset is envelope_size*(member.ordinal - 1) and the envelope takes
517            //   envelope_size bytes, there is always sufficient room.
518            fidl::encoding::encode_in_envelope_optional::<
519                fidl::encoding::Endpoint<
520                    fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>,
521                >,
522                fidl::encoding::DefaultFuchsiaResourceDialect,
523            >(
524                self.outgoing_dir.as_mut().map(
525                    <fidl::encoding::Endpoint<
526                        fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>,
527                    > as fidl::encoding::ResourceTypeMarker>::take_or_borrow,
528                ),
529                encoder,
530                offset + cur_offset,
531                depth,
532            )?;
533
534            _prev_end_offset = cur_offset + envelope_size;
535            if 2 > max_ordinal {
536                return Ok(());
537            }
538
539            // Write at offset+(ordinal-1)*envelope_size, since ordinals are one-based and envelopes
540            // are envelope_size bytes.
541            let cur_offset: usize = (2 - 1) * envelope_size;
542
543            // Zero reserved fields.
544            encoder.padding(offset + _prev_end_offset, cur_offset - _prev_end_offset);
545
546            // Safety:
547            // - bytes_len is calculated to fit envelope_size*max(member.ordinal).
548            // - Since cur_offset is envelope_size*(member.ordinal - 1) and the envelope takes
549            //   envelope_size bytes, there is always sufficient room.
550            fidl::encoding::encode_in_envelope_optional::<fidl_fuchsia_component_sandbox::DictionaryRef, fidl::encoding::DefaultFuchsiaResourceDialect>(
551            self.escrowed_dictionary.as_mut().map(<fidl_fuchsia_component_sandbox::DictionaryRef as fidl::encoding::ResourceTypeMarker>::take_or_borrow),
552            encoder, offset + cur_offset, depth
553        )?;
554
555            _prev_end_offset = cur_offset + envelope_size;
556
557            Ok(())
558        }
559    }
560
561    impl fidl::encoding::Decode<Self, fidl::encoding::DefaultFuchsiaResourceDialect>
562        for LifecycleOnEscrowRequest
563    {
564        #[inline(always)]
565        fn new_empty() -> Self {
566            Self::default()
567        }
568
569        unsafe fn decode(
570            &mut self,
571            decoder: &mut fidl::encoding::Decoder<
572                '_,
573                fidl::encoding::DefaultFuchsiaResourceDialect,
574            >,
575            offset: usize,
576            mut depth: fidl::encoding::Depth,
577        ) -> fidl::Result<()> {
578            decoder.debug_check_bounds::<Self>(offset);
579            let len = match fidl::encoding::decode_vector_header(decoder, offset)? {
580                None => return Err(fidl::Error::NotNullable),
581                Some(len) => len,
582            };
583            // Calling decoder.out_of_line_offset(0) is not allowed.
584            if len == 0 {
585                return Ok(());
586            };
587            depth.increment()?;
588            let envelope_size = 8;
589            let bytes_len = len * envelope_size;
590            let offset = decoder.out_of_line_offset(bytes_len)?;
591            // Decode the envelope for each type.
592            let mut _next_ordinal_to_read = 0;
593            let mut next_offset = offset;
594            let end_offset = offset + bytes_len;
595            _next_ordinal_to_read += 1;
596            if next_offset >= end_offset {
597                return Ok(());
598            }
599
600            // Decode unknown envelopes for gaps in ordinals.
601            while _next_ordinal_to_read < 1 {
602                fidl::encoding::decode_unknown_envelope(decoder, next_offset, depth)?;
603                _next_ordinal_to_read += 1;
604                next_offset += envelope_size;
605            }
606
607            let next_out_of_line = decoder.next_out_of_line();
608            let handles_before = decoder.remaining_handles();
609            if let Some((inlined, num_bytes, num_handles)) =
610                fidl::encoding::decode_envelope_header(decoder, next_offset)?
611            {
612                let member_inline_size = <fidl::encoding::Endpoint<
613                    fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>,
614                > as fidl::encoding::TypeMarker>::inline_size(
615                    decoder.context
616                );
617                if inlined != (member_inline_size <= 4) {
618                    return Err(fidl::Error::InvalidInlineBitInEnvelope);
619                }
620                let inner_offset;
621                let mut inner_depth = depth.clone();
622                if inlined {
623                    decoder.check_inline_envelope_padding(next_offset, member_inline_size)?;
624                    inner_offset = next_offset;
625                } else {
626                    inner_offset = decoder.out_of_line_offset(member_inline_size)?;
627                    inner_depth.increment()?;
628                }
629                let val_ref = self.outgoing_dir.get_or_insert_with(|| {
630                    fidl::new_empty!(
631                        fidl::encoding::Endpoint<
632                            fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>,
633                        >,
634                        fidl::encoding::DefaultFuchsiaResourceDialect
635                    )
636                });
637                fidl::decode!(
638                    fidl::encoding::Endpoint<
639                        fidl::endpoints::ServerEnd<fidl_fuchsia_io::DirectoryMarker>,
640                    >,
641                    fidl::encoding::DefaultFuchsiaResourceDialect,
642                    val_ref,
643                    decoder,
644                    inner_offset,
645                    inner_depth
646                )?;
647                if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize)
648                {
649                    return Err(fidl::Error::InvalidNumBytesInEnvelope);
650                }
651                if handles_before != decoder.remaining_handles() + (num_handles as usize) {
652                    return Err(fidl::Error::InvalidNumHandlesInEnvelope);
653                }
654            }
655
656            next_offset += envelope_size;
657            _next_ordinal_to_read += 1;
658            if next_offset >= end_offset {
659                return Ok(());
660            }
661
662            // Decode unknown envelopes for gaps in ordinals.
663            while _next_ordinal_to_read < 2 {
664                fidl::encoding::decode_unknown_envelope(decoder, next_offset, depth)?;
665                _next_ordinal_to_read += 1;
666                next_offset += envelope_size;
667            }
668
669            let next_out_of_line = decoder.next_out_of_line();
670            let handles_before = decoder.remaining_handles();
671            if let Some((inlined, num_bytes, num_handles)) =
672                fidl::encoding::decode_envelope_header(decoder, next_offset)?
673            {
674                let member_inline_size = <fidl_fuchsia_component_sandbox::DictionaryRef as fidl::encoding::TypeMarker>::inline_size(decoder.context);
675                if inlined != (member_inline_size <= 4) {
676                    return Err(fidl::Error::InvalidInlineBitInEnvelope);
677                }
678                let inner_offset;
679                let mut inner_depth = depth.clone();
680                if inlined {
681                    decoder.check_inline_envelope_padding(next_offset, member_inline_size)?;
682                    inner_offset = next_offset;
683                } else {
684                    inner_offset = decoder.out_of_line_offset(member_inline_size)?;
685                    inner_depth.increment()?;
686                }
687                let val_ref = self.escrowed_dictionary.get_or_insert_with(|| {
688                    fidl::new_empty!(
689                        fidl_fuchsia_component_sandbox::DictionaryRef,
690                        fidl::encoding::DefaultFuchsiaResourceDialect
691                    )
692                });
693                fidl::decode!(
694                    fidl_fuchsia_component_sandbox::DictionaryRef,
695                    fidl::encoding::DefaultFuchsiaResourceDialect,
696                    val_ref,
697                    decoder,
698                    inner_offset,
699                    inner_depth
700                )?;
701                if !inlined && decoder.next_out_of_line() != next_out_of_line + (num_bytes as usize)
702                {
703                    return Err(fidl::Error::InvalidNumBytesInEnvelope);
704                }
705                if handles_before != decoder.remaining_handles() + (num_handles as usize) {
706                    return Err(fidl::Error::InvalidNumHandlesInEnvelope);
707                }
708            }
709
710            next_offset += envelope_size;
711
712            // Decode the remaining unknown envelopes.
713            while next_offset < end_offset {
714                _next_ordinal_to_read += 1;
715                fidl::encoding::decode_unknown_envelope(decoder, next_offset, depth)?;
716                next_offset += envelope_size;
717            }
718
719            Ok(())
720        }
721    }
722}