// WARNING: This file is machine generated by fidlgen.

#![allow(
	deprecated, // FIDL Impl struct pattern is referenced internally
	unused_parens, // one-element-tuple-case is not a tuple
	unused_mut, // not all args require mutation, but many do
	nonstandard_style, // auto-caps does its best, but is not always successful
)]
#![recursion_limit = "512"]

#[cfg(target_os = "fuchsia")]
#[allow(unused_imports)]
use fuchsia_zircon as zx;

#[allow(unused_imports)]
use {
    bitflags::bitflags,
    fidl::{
        client::{decode_transaction_body_fut, QueryResponseFut},
        fidl_empty_struct, fidl_flexible_bits, fidl_flexible_enum, fidl_strict_bits,
        fidl_strict_enum, fidl_struct, fidl_struct_copy, fidl_table, fidl_xunion,
        wrap_handle_metadata,
    },
    fuchsia_zircon_status as zx_status,
    futures::future::{self, MaybeDone, TryFutureExt},
};

const _FIDL_TRACE_BINDINGS_RUST: u32 = 6;
wrap_handle_metadata!(
    HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT,
    fidl::ObjectType::CHANNEL,
    fidl::Rights::CHANNEL_DEFAULT
);

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ParentMarker;

impl fidl::endpoints::ServiceMarker for ParentMarker {
    type Proxy = ParentProxy;
    type RequestStream = ParentRequestStream;
    const DEBUG_NAME: &'static str = "(anonymous) Parent";
}

pub trait ParentProxyInterface: Send + Sync {
    fn first(&self, request: fidl::endpoints::ServerEnd<ParentMarker>) -> Result<(), fidl::Error>;
}

#[derive(Debug)]
#[cfg(target_os = "fuchsia")]
pub struct ParentSynchronousProxy {
    client: fidl::client::sync::Client,
}

#[cfg(target_os = "fuchsia")]
impl ParentSynchronousProxy {
    pub fn new(channel: fidl::Channel) -> Self {
        Self { client: fidl::client::sync::Client::new(channel) }
    }

    pub fn into_channel(self) -> fidl::Channel {
        self.client.into_channel()
    }
    pub fn first(
        &mut self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x2a592d0a81dac39b)
    }
}

#[derive(Debug, Clone)]
pub struct ParentProxy {
    client: fidl::client::Client,
}

impl fidl::endpoints::Proxy for ParentProxy {
    type Service = ParentMarker;

    fn from_channel(inner: fidl::AsyncChannel) -> Self {
        Self::new(inner)
    }

    fn into_channel(self) -> Result<::fidl::AsyncChannel, Self> {
        self.client.into_channel().map_err(|client| Self { client })
    }

    fn as_channel(&self) -> &::fidl::AsyncChannel {
        self.client.as_channel()
    }
}

impl ParentProxy {
    /// Create a new Proxy for Parent
    pub fn new(channel: fidl::AsyncChannel) -> Self {
        let service_name = <ParentMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME;
        Self { client: fidl::client::Client::new(channel, service_name) }
    }

    /// Get a Stream of events from the remote end of the Parent protocol
    ///
    /// # Panics
    ///
    /// Panics if the event stream was already taken.
    pub fn take_event_stream(&self) -> ParentEventStream {
        ParentEventStream { event_receiver: self.client.take_event_receiver() }
    }
    pub fn first(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        ParentProxyInterface::first(self, request)
    }
}

impl ParentProxyInterface for ParentProxy {
    fn first(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x2a592d0a81dac39b)
    }
}

pub struct ParentEventStream {
    event_receiver: fidl::client::EventReceiver,
}

impl std::marker::Unpin for ParentEventStream {}

impl futures::stream::FusedStream for ParentEventStream {
    fn is_terminated(&self) -> bool {
        self.event_receiver.is_terminated()
    }
}

impl futures::Stream for ParentEventStream {
    type Item = Result<ParentEvent, fidl::Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Option<Self::Item>> {
        let mut buf = match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
            &mut self.event_receiver,
            cx
        )?) {
            Some(buf) => buf,
            None => return std::task::Poll::Ready(None),
        };
        let (bytes, _handles) = buf.split_mut();
        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

        std::task::Poll::Ready(Some(match tx_header.ordinal() {
            _ => Err(fidl::Error::UnknownOrdinal {
                ordinal: tx_header.ordinal(),
                service_name: <ParentMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
            }),
        }))
    }
}

#[derive(Debug)]
pub enum ParentEvent {}

impl ParentEvent {}

/// A type which can be used to send responses and events into a borrowed channel.
///
/// Note: this should only be used when the channel must be temporarily
/// borrowed. For a typical sending of events, use the send_ methods
/// on the ControlHandle types, which can be acquired through a
/// RequestStream or Responder type.
#[deprecated(note = "Use ParentRequestStream / Responder instead")]
pub struct ParentServerSender<'a> {
    // Some protocols don't define events which would render this channel unused.
    #[allow(unused)]
    channel: &'a fidl::Channel,
}

impl<'a> ParentServerSender<'a> {
    pub fn new(channel: &'a fidl::Channel) -> Self {
        Self { channel }
    }
}

/// A Stream of incoming requests for Parent
pub struct ParentRequestStream {
    inner: std::sync::Arc<fidl::ServeInner>,
    is_terminated: bool,
}

impl std::marker::Unpin for ParentRequestStream {}

impl futures::stream::FusedStream for ParentRequestStream {
    fn is_terminated(&self) -> bool {
        self.is_terminated
    }
}

impl fidl::endpoints::RequestStream for ParentRequestStream {
    type Service = ParentMarker;

    /// Consume a channel to make a ParentRequestStream
    fn from_channel(channel: fidl::AsyncChannel) -> Self {
        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
    }

    /// ControlHandle for the remote connection
    type ControlHandle = ParentControlHandle;

    /// ControlHandle for the remote connection
    fn control_handle(&self) -> Self::ControlHandle {
        ParentControlHandle { inner: self.inner.clone() }
    }

    fn into_inner(self) -> (::std::sync::Arc<fidl::ServeInner>, bool) {
        (self.inner, self.is_terminated)
    }

    fn from_inner(inner: std::sync::Arc<fidl::ServeInner>, is_terminated: bool) -> Self {
        Self { inner, is_terminated }
    }
}

impl futures::Stream for ParentRequestStream {
    type Item = Result<ParentRequest, fidl::Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Option<Self::Item>> {
        let this = &mut *self;
        if this.inner.poll_shutdown(cx) {
            this.is_terminated = true;
            return std::task::Poll::Ready(None);
        }
        if this.is_terminated {
            panic!("polled ParentRequestStream after completion");
        }
        fidl::encoding::with_tls_decode_buf(|bytes, handles| {
            match this.inner.channel().read_etc(cx, bytes, handles) {
                std::task::Poll::Ready(Ok(())) => {}
                std::task::Poll::Pending => return std::task::Poll::Pending,
                std::task::Poll::Ready(Err(zx_status::Status::PEER_CLOSED)) => {
                    this.is_terminated = true;
                    return std::task::Poll::Ready(None);
                }
                std::task::Poll::Ready(Err(e)) => {
                    return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(e))))
                }
            }

            // A message has been received from the channel
            let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
            if !header.is_compatible() {
                return std::task::Poll::Ready(Some(Err(fidl::Error::IncompatibleMagicNumber(
                    header.magic_number(),
                ))));
            }

            std::task::Poll::Ready(Some(match header.ordinal() {
                0x2a592d0a81dac39b => {
                    let mut req: (
                        HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                            fidl::endpoints::ServerEnd<ParentMarker>,
                        >,
                    ) = fidl::encoding::Decodable::new_empty();
                    fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ParentFirstRequest");
                    fidl::trace_blob!("fidl:blob", "decode", bytes);
                    fidl::encoding::Decoder::decode_into(&header, _body_bytes, handles, &mut req)?;
                    fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => handles.len() as u32);
                    let control_handle = ParentControlHandle { inner: this.inner.clone() };

                    Ok(ParentRequest::First { request: req.0.into_inner(), control_handle })
                }
                _ => Err(fidl::Error::UnknownOrdinal {
                    ordinal: header.ordinal(),
                    service_name: <ParentMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
                }),
            }))
        })
    }
}

/// Represents a single request.
/// RequestMessages should only be used for manual deserialization when higher level
/// structs such as RequestStream cannot be used. One usually would only encounter
/// such scenarios when working with legacy FIDL code (prior to FIDL generated client/server bindings).
#[derive(Debug)]
#[deprecated(note = "Use ParentRequest instead")]
pub enum ParentRequestMessage {
    First { request: fidl::endpoints::ServerEnd<ParentMarker> },
}

impl ParentRequestMessage {
    pub fn decode(
        bytes: &[u8],
        _handles: &mut [fidl::HandleInfo],
    ) -> Result<ParentRequestMessage, fidl::Error> {
        let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

        match header.ordinal() {
            0x2a592d0a81dac39b => {
                let mut out_tuple: (
                    HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                        fidl::endpoints::ServerEnd<ParentMarker>,
                    >,
                ) = fidl::encoding::Decodable::new_empty();
                fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ParentFirstRequest");
                fidl::trace_blob!("fidl:blob", "decode", bytes);
                fidl::encoding::Decoder::decode_into(
                    &header,
                    _body_bytes,
                    _handles,
                    &mut out_tuple,
                )?;
                fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => _handles.len() as u32);

                Ok(ParentRequestMessage::First { request: out_tuple.0.into_inner() })
            }
            _ => Err(fidl::Error::UnknownOrdinal {
                ordinal: header.ordinal(),
                service_name: <ParentMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
            }),
        }
    }
}
#[derive(Debug)]
pub enum ParentRequest {
    First { request: fidl::endpoints::ServerEnd<ParentMarker>, control_handle: ParentControlHandle },
}

impl ParentRequest {
    #[allow(irrefutable_let_patterns)]
    pub fn into_first(
        self,
    ) -> Option<(fidl::endpoints::ServerEnd<ParentMarker>, ParentControlHandle)> {
        if let ParentRequest::First { request, control_handle } = self {
            Some((request, control_handle))
        } else {
            None
        }
    }

    /// Name of the method defined in FIDL
    pub fn method_name(&self) -> &'static str {
        match *self {
            ParentRequest::First { .. } => "first",
        }
    }
}

pub struct ParentEncoder;

impl ParentEncoder {
    pub fn encode_first_request<'a>(
        out_bytes: &'a mut Vec<u8>,
        out_handles: &'a mut Vec<fidl::HandleDisposition<'static>>,
        mut in_request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        let header = fidl::encoding::TransactionHeader::new(0, 0x2a592d0a81dac39b);
        let mut body = (in_request,);
        let mut msg = fidl::encoding::TransactionMessage { header, body: &mut body };
        fidl::duration_begin!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ParentFirstRequest");
        fidl::encoding::Encoder::encode(out_bytes, out_handles, &mut msg)?;
        fidl::trace_blob!("fidl:blob", "encode", out_bytes.as_slice());
        fidl::duration_end!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => out_bytes.len() as u32, "handle_count" => out_handles.len() as u32);
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct ParentControlHandle {
    inner: std::sync::Arc<fidl::ServeInner>,
}

impl ParentControlHandle {
    /// Set the server to shutdown. The underlying channel is only closed the
    /// next time the stream is polled.
    pub fn shutdown(&self) {
        self.inner.shutdown()
    }

    pub fn shutdown_with_epitaph(&self, status: zx_status::Status) {
        self.inner.shutdown_with_epitaph(status)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ChildMarker;

impl fidl::endpoints::ServiceMarker for ChildMarker {
    type Proxy = ChildProxy;
    type RequestStream = ChildRequestStream;
    const DEBUG_NAME: &'static str = "(anonymous) Child";
}

pub trait ChildProxyInterface: Send + Sync {
    fn first(&self, request: fidl::endpoints::ServerEnd<ParentMarker>) -> Result<(), fidl::Error>;
    fn second(&self, request: fidl::endpoints::ServerEnd<ParentMarker>) -> Result<(), fidl::Error>;
}

#[derive(Debug)]
#[cfg(target_os = "fuchsia")]
pub struct ChildSynchronousProxy {
    client: fidl::client::sync::Client,
}

#[cfg(target_os = "fuchsia")]
impl ChildSynchronousProxy {
    pub fn new(channel: fidl::Channel) -> Self {
        Self { client: fidl::client::sync::Client::new(channel) }
    }

    pub fn into_channel(self) -> fidl::Channel {
        self.client.into_channel()
    }
    pub fn first(
        &mut self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x2a592d0a81dac39b)
    }
    pub fn second(
        &mut self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x6cba5c5e01fee86)
    }
}

#[derive(Debug, Clone)]
pub struct ChildProxy {
    client: fidl::client::Client,
}

impl fidl::endpoints::Proxy for ChildProxy {
    type Service = ChildMarker;

    fn from_channel(inner: fidl::AsyncChannel) -> Self {
        Self::new(inner)
    }

    fn into_channel(self) -> Result<::fidl::AsyncChannel, Self> {
        self.client.into_channel().map_err(|client| Self { client })
    }

    fn as_channel(&self) -> &::fidl::AsyncChannel {
        self.client.as_channel()
    }
}

impl ChildProxy {
    /// Create a new Proxy for Child
    pub fn new(channel: fidl::AsyncChannel) -> Self {
        let service_name = <ChildMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME;
        Self { client: fidl::client::Client::new(channel, service_name) }
    }

    /// Get a Stream of events from the remote end of the Child protocol
    ///
    /// # Panics
    ///
    /// Panics if the event stream was already taken.
    pub fn take_event_stream(&self) -> ChildEventStream {
        ChildEventStream { event_receiver: self.client.take_event_receiver() }
    }
    pub fn first(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        ChildProxyInterface::first(self, request)
    }
    pub fn second(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        ChildProxyInterface::second(self, request)
    }
}

impl ChildProxyInterface for ChildProxy {
    fn first(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x2a592d0a81dac39b)
    }
    fn second(
        &self,
        mut request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        self.client.send(&mut (request), 0x6cba5c5e01fee86)
    }
}

pub struct ChildEventStream {
    event_receiver: fidl::client::EventReceiver,
}

impl std::marker::Unpin for ChildEventStream {}

impl futures::stream::FusedStream for ChildEventStream {
    fn is_terminated(&self) -> bool {
        self.event_receiver.is_terminated()
    }
}

impl futures::Stream for ChildEventStream {
    type Item = Result<ChildEvent, fidl::Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Option<Self::Item>> {
        let mut buf = match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
            &mut self.event_receiver,
            cx
        )?) {
            Some(buf) => buf,
            None => return std::task::Poll::Ready(None),
        };
        let (bytes, _handles) = buf.split_mut();
        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

        std::task::Poll::Ready(Some(match tx_header.ordinal() {
            _ => Err(fidl::Error::UnknownOrdinal {
                ordinal: tx_header.ordinal(),
                service_name: <ChildMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
            }),
        }))
    }
}

#[derive(Debug)]
pub enum ChildEvent {}

impl ChildEvent {}

/// A type which can be used to send responses and events into a borrowed channel.
///
/// Note: this should only be used when the channel must be temporarily
/// borrowed. For a typical sending of events, use the send_ methods
/// on the ControlHandle types, which can be acquired through a
/// RequestStream or Responder type.
#[deprecated(note = "Use ChildRequestStream / Responder instead")]
pub struct ChildServerSender<'a> {
    // Some protocols don't define events which would render this channel unused.
    #[allow(unused)]
    channel: &'a fidl::Channel,
}

impl<'a> ChildServerSender<'a> {
    pub fn new(channel: &'a fidl::Channel) -> Self {
        Self { channel }
    }
}

/// A Stream of incoming requests for Child
pub struct ChildRequestStream {
    inner: std::sync::Arc<fidl::ServeInner>,
    is_terminated: bool,
}

impl std::marker::Unpin for ChildRequestStream {}

impl futures::stream::FusedStream for ChildRequestStream {
    fn is_terminated(&self) -> bool {
        self.is_terminated
    }
}

impl fidl::endpoints::RequestStream for ChildRequestStream {
    type Service = ChildMarker;

    /// Consume a channel to make a ChildRequestStream
    fn from_channel(channel: fidl::AsyncChannel) -> Self {
        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
    }

    /// ControlHandle for the remote connection
    type ControlHandle = ChildControlHandle;

    /// ControlHandle for the remote connection
    fn control_handle(&self) -> Self::ControlHandle {
        ChildControlHandle { inner: self.inner.clone() }
    }

    fn into_inner(self) -> (::std::sync::Arc<fidl::ServeInner>, bool) {
        (self.inner, self.is_terminated)
    }

    fn from_inner(inner: std::sync::Arc<fidl::ServeInner>, is_terminated: bool) -> Self {
        Self { inner, is_terminated }
    }
}

impl futures::Stream for ChildRequestStream {
    type Item = Result<ChildRequest, fidl::Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Option<Self::Item>> {
        let this = &mut *self;
        if this.inner.poll_shutdown(cx) {
            this.is_terminated = true;
            return std::task::Poll::Ready(None);
        }
        if this.is_terminated {
            panic!("polled ChildRequestStream after completion");
        }
        fidl::encoding::with_tls_decode_buf(|bytes, handles| {
            match this.inner.channel().read_etc(cx, bytes, handles) {
                std::task::Poll::Ready(Ok(())) => {}
                std::task::Poll::Pending => return std::task::Poll::Pending,
                std::task::Poll::Ready(Err(zx_status::Status::PEER_CLOSED)) => {
                    this.is_terminated = true;
                    return std::task::Poll::Ready(None);
                }
                std::task::Poll::Ready(Err(e)) => {
                    return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(e))))
                }
            }

            // A message has been received from the channel
            let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
            if !header.is_compatible() {
                return std::task::Poll::Ready(Some(Err(fidl::Error::IncompatibleMagicNumber(
                    header.magic_number(),
                ))));
            }

            std::task::Poll::Ready(Some(match header.ordinal() {
                0x2a592d0a81dac39b => {
                    let mut req: (
                        HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                            fidl::endpoints::ServerEnd<ParentMarker>,
                        >,
                    ) = fidl::encoding::Decodable::new_empty();
                    fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildFirstRequest");
                    fidl::trace_blob!("fidl:blob", "decode", bytes);
                    fidl::encoding::Decoder::decode_into(&header, _body_bytes, handles, &mut req)?;
                    fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => handles.len() as u32);
                    let control_handle = ChildControlHandle { inner: this.inner.clone() };

                    Ok(ChildRequest::First { request: req.0.into_inner(), control_handle })
                }
                0x6cba5c5e01fee86 => {
                    let mut req: (
                        HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                            fidl::endpoints::ServerEnd<ParentMarker>,
                        >,
                    ) = fidl::encoding::Decodable::new_empty();
                    fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildSecondRequest");
                    fidl::trace_blob!("fidl:blob", "decode", bytes);
                    fidl::encoding::Decoder::decode_into(&header, _body_bytes, handles, &mut req)?;
                    fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => handles.len() as u32);
                    let control_handle = ChildControlHandle { inner: this.inner.clone() };

                    Ok(ChildRequest::Second { request: req.0.into_inner(), control_handle })
                }
                _ => Err(fidl::Error::UnknownOrdinal {
                    ordinal: header.ordinal(),
                    service_name: <ChildMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
                }),
            }))
        })
    }
}

/// Represents a single request.
/// RequestMessages should only be used for manual deserialization when higher level
/// structs such as RequestStream cannot be used. One usually would only encounter
/// such scenarios when working with legacy FIDL code (prior to FIDL generated client/server bindings).
#[derive(Debug)]
#[deprecated(note = "Use ChildRequest instead")]
pub enum ChildRequestMessage {
    First { request: fidl::endpoints::ServerEnd<ParentMarker> },
    Second { request: fidl::endpoints::ServerEnd<ParentMarker> },
}

impl ChildRequestMessage {
    pub fn decode(
        bytes: &[u8],
        _handles: &mut [fidl::HandleInfo],
    ) -> Result<ChildRequestMessage, fidl::Error> {
        let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

        match header.ordinal() {
            0x2a592d0a81dac39b => {
                let mut out_tuple: (
                    HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                        fidl::endpoints::ServerEnd<ParentMarker>,
                    >,
                ) = fidl::encoding::Decodable::new_empty();
                fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildFirstRequest");
                fidl::trace_blob!("fidl:blob", "decode", bytes);
                fidl::encoding::Decoder::decode_into(
                    &header,
                    _body_bytes,
                    _handles,
                    &mut out_tuple,
                )?;
                fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => _handles.len() as u32);

                Ok(ChildRequestMessage::First { request: out_tuple.0.into_inner() })
            }
            0x6cba5c5e01fee86 => {
                let mut out_tuple: (
                    HandleWrapperObjectTypeCHANNELRightsCHANNEL_DEFAULT<
                        fidl::endpoints::ServerEnd<ParentMarker>,
                    >,
                ) = fidl::encoding::Decodable::new_empty();
                fidl::duration_begin!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildSecondRequest");
                fidl::trace_blob!("fidl:blob", "decode", bytes);
                fidl::encoding::Decoder::decode_into(
                    &header,
                    _body_bytes,
                    _handles,
                    &mut out_tuple,
                )?;
                fidl::duration_end!("fidl", "decode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => bytes.len() as u32, "handle_count" => _handles.len() as u32);

                Ok(ChildRequestMessage::Second { request: out_tuple.0.into_inner() })
            }
            _ => Err(fidl::Error::UnknownOrdinal {
                ordinal: header.ordinal(),
                service_name: <ChildMarker as fidl::endpoints::ServiceMarker>::DEBUG_NAME,
            }),
        }
    }
}
#[derive(Debug)]
pub enum ChildRequest {
    First { request: fidl::endpoints::ServerEnd<ParentMarker>, control_handle: ChildControlHandle },
    Second { request: fidl::endpoints::ServerEnd<ParentMarker>, control_handle: ChildControlHandle },
}

impl ChildRequest {
    #[allow(irrefutable_let_patterns)]
    pub fn into_first(
        self,
    ) -> Option<(fidl::endpoints::ServerEnd<ParentMarker>, ChildControlHandle)> {
        if let ChildRequest::First { request, control_handle } = self {
            Some((request, control_handle))
        } else {
            None
        }
    }

    #[allow(irrefutable_let_patterns)]
    pub fn into_second(
        self,
    ) -> Option<(fidl::endpoints::ServerEnd<ParentMarker>, ChildControlHandle)> {
        if let ChildRequest::Second { request, control_handle } = self {
            Some((request, control_handle))
        } else {
            None
        }
    }

    /// Name of the method defined in FIDL
    pub fn method_name(&self) -> &'static str {
        match *self {
            ChildRequest::First { .. } => "first",
            ChildRequest::Second { .. } => "second",
        }
    }
}

pub struct ChildEncoder;

impl ChildEncoder {
    pub fn encode_first_request<'a>(
        out_bytes: &'a mut Vec<u8>,
        out_handles: &'a mut Vec<fidl::HandleDisposition<'static>>,
        mut in_request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        let header = fidl::encoding::TransactionHeader::new(0, 0x2a592d0a81dac39b);
        let mut body = (in_request,);
        let mut msg = fidl::encoding::TransactionMessage { header, body: &mut body };
        fidl::duration_begin!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildFirstRequest");
        fidl::encoding::Encoder::encode(out_bytes, out_handles, &mut msg)?;
        fidl::trace_blob!("fidl:blob", "encode", out_bytes.as_slice());
        fidl::duration_end!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => out_bytes.len() as u32, "handle_count" => out_handles.len() as u32);
        Ok(())
    }
    pub fn encode_second_request<'a>(
        out_bytes: &'a mut Vec<u8>,
        out_handles: &'a mut Vec<fidl::HandleDisposition<'static>>,
        mut in_request: fidl::endpoints::ServerEnd<ParentMarker>,
    ) -> Result<(), fidl::Error> {
        let header = fidl::encoding::TransactionHeader::new(0, 0x6cba5c5e01fee86);
        let mut body = (in_request,);
        let mut msg = fidl::encoding::TransactionMessage { header, body: &mut body };
        fidl::duration_begin!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "name" => "fidl.test.inheritancewithrecursivedecl/ChildSecondRequest");
        fidl::encoding::Encoder::encode(out_bytes, out_handles, &mut msg)?;
        fidl::trace_blob!("fidl:blob", "encode", out_bytes.as_slice());
        fidl::duration_end!("fidl", "encode", "bindings" => _FIDL_TRACE_BINDINGS_RUST, "size" => out_bytes.len() as u32, "handle_count" => out_handles.len() as u32);
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct ChildControlHandle {
    inner: std::sync::Arc<fidl::ServeInner>,
}

impl ChildControlHandle {
    /// Set the server to shutdown. The underlying channel is only closed the
    /// next time the stream is polled.
    pub fn shutdown(&self) {
        self.inner.shutdown()
    }

    pub fn shutdown_with_epitaph(&self, status: zx_status::Status) {
        self.inner.shutdown_with_epitaph(status)
    }
}
