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

#![feature(futures_api, pin, arbitrary_self_types, nll)]
#![allow(warnings)]

extern crate fuchsia_async;
extern crate fuchsia_zircon as zx;
#[macro_use]
extern crate fidl;
#[macro_use]
extern crate futures;
use fidl::encoding::{Encodable, Decodable};
use futures::{Future, Stream, StreamExt};
use std::ops::Deref;


/// const comment #1
///
/// const comment #3
pub const C: i32 = 4;

fidl_union! {
  name: Union,
  members: [
    Field {
      ty: i32,
      offset: 4,
    },
  ],
  size: 8,
  align: 4,
}

#[derive(Debug, PartialEq)]
/// struct comment #1
///
/// struct comment #3
pub struct Struct {
  /// struct member comment #1
  ///
  /// struct member comment #3
  pub field: i32,
}

fidl_struct! {
  name: Struct,
  members: [
    field {
      ty: i32,
      offset: 0,
    },
  ],
  size: 4,
  align: 4,
}

/// table comment #1
///
/// table comment #3
#[derive(Debug, PartialEq)]
pub struct Table {
  /// table field comment #1
  ///
  /// table field comment #3
  pub field: Option<i32>,
}

fidl_table! {
  name: Table,
  members: {
    field {
      ty: i32,
      ordinal: 1,
    },
  },
}


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

impl fidl::endpoints::ServiceMarker for InterfaceMarker {
	type Proxy = InterfaceProxy;
	type RequestStream = InterfaceRequestStream;
	const NAME: &'static str = "";
}

pub trait InterfaceProxyInterface: Send + Sync {
	fn method(&self,
	)-> Result<(), fidl::Error>;
}

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

impl InterfaceSynchronousProxy {
	pub fn new(channel: zx::Channel) -> Self {
		Self { client: fidl::client::sync::Client::new(channel) }
	}

	pub fn into_channel(self) -> zx::Channel {
		self.client.into_channel()
	}
	/// method comment #1
	///
	/// method comment #3
	pub fn method(&mut self,) -> Result<(), fidl::Error> {self.client.send(&mut (),
				1061382220,
			)}
}

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

impl fidl::endpoints::Proxy for InterfaceProxy {
	fn from_channel(inner: ::fuchsia_async::Channel) -> Self {
		Self::new(inner)
	}
}

impl Deref for InterfaceProxy {
	type Target = fidl::client::Client;

	fn deref(&self) -> &Self::Target {
		&self.client
	}
}

/// Proxy object for communicating with interface Interface
impl InterfaceProxy {
        /// Create a new Proxy for Interface
   pub fn new(channel: ::fuchsia_async::Channel) -> Self {
		Self { client: fidl::client::Client::new(channel) }
	}

	/// Attempt to convert the Proxy back into a channel.
	///
	/// This will only succeed if there are no active clones of this Proxy
	/// and no currently-alive EventStream or response futures that came from
	/// this Proxy.
	pub fn into_channel(self) -> Result<::fuchsia_async::Channel, Self> {
		self.client.into_channel().map_err(|client| Self { client })
	}

        /// Get a Stream of events from the remote end of the Interface interface
	pub fn take_event_stream(&self) -> InterfaceEventStream {
		InterfaceEventStream {
			event_receiver: self.client.take_event_receiver(),
		}
	}
	/// method comment #1
	///
	/// method comment #3
	pub fn method(&self,
	)-> Result<(), fidl::Error> {
		InterfaceProxyInterface::method(self,
		)
	}
}

impl InterfaceProxyInterface for InterfaceProxy {
	fn method(&self,
	)-> Result<(), fidl::Error> {
		self.client.send(&mut (), 1061382220)
	}}

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

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

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

impl Stream for InterfaceEventStream {
	type Item = Result<InterfaceEvent, fidl::Error>;

	fn poll_next(mut self: ::std::pin::Pin<&mut Self>, lw: &futures::task::LocalWaker)
		-> futures::Poll<Option<Self::Item>>
	{
		let mut buf = match ready!(self.event_receiver.poll_next_unpin(lw)?) {
			Some(buf) => buf,
			None => return futures::Poll::Ready(None),
		};
		let (bytes, handles) = buf.split_mut();
		let (tx_header, body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
		futures::Poll::Ready(Some(match tx_header.ordinal {
			_ => Err(fidl::Error::UnknownOrdinal {
				ordinal: tx_header.ordinal,
				service_name: <InterfaceMarker as fidl::endpoints::ServiceMarker>::NAME,
			})
		}))
	}
}

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

#[deprecated(note = "use InterfaceRequestStream instead")]
pub trait Interface {
	type OnOpenFut: Future<Output = ()> + Send;
	fn on_open(&mut self, control_handle: InterfaceControlHandle) -> Self::OnOpenFut;
	type MethodFut: Future<Output = ()> + Send;
	fn method (&mut self,
		control_handle: InterfaceControlHandle
	) -> Self::MethodFut;
	

	fn serve(mut self, channel: ::fuchsia_async::Channel)
		-> InterfaceServer<Self>
	where Self: Sized
	{
		let inner = ::std::sync::Arc::new(fidl::ServeInner::new(channel));
		let on_open_fut = self.on_open(
			InterfaceControlHandle {
				inner: inner.clone(),
			}
		);
		InterfaceServer {
			server: self,
			inner: inner.clone(),
			msg_buf: zx::MessageBuf::new(),
			on_open_fut: Some(on_open_fut),method_futures: futures::stream::FuturesUnordered::new(),
		}
	}
}

pub struct InterfaceServer<T: Interface> {
	server: T,
	inner: ::std::sync::Arc<fidl::ServeInner>,
	msg_buf: zx::MessageBuf,
	on_open_fut: Option<T::OnOpenFut>,method_futures: futures::stream::FuturesUnordered<T::MethodFut>,
}

// Safety: only the OnOpen fut is held directly, so it's the only one that
// is projected to, so it's the only one that needs to be Unpin for the Impl
// struct to be Unpin.
impl<T: Interface> ::std::marker::Unpin for InterfaceServer<T>
where T::OnOpenFut: ::std::marker::Unpin,
{}

impl<T: Interface> InterfaceServer<T> {
	pub fn control_handle(&self) -> InterfaceControlHandle {
		InterfaceControlHandle {
			inner: self.inner.clone(),
		}
	}
}

impl<T: Interface> futures::Future for InterfaceServer<T> {
	type Output = Result<(), fidl::Error>;

	fn poll(
		mut self: ::std::pin::Pin<&mut Self>,
		lw: &::futures::task::LocalWaker,
	) -> futures::Poll<Self::Output> {
		// safety: the only potentially !Unpin field is on_open_fut, which we make sure
		// isn't moved below
		let this = unsafe { ::std::pin::Pin::get_unchecked_mut(self) };
		loop {
		let mut made_progress_this_loop_iter = false;

		if this.inner.poll_shutdown(lw) {
			return futures::Poll::Ready(Ok(()));
		}

		unsafe {
			// Safety: ensure that on_open isn't moved
			let completed_on_open = if let Some(on_open_fut) = &mut this.on_open_fut {
				match Future::poll(::std::pin::Pin::new_unchecked(on_open_fut), lw) {
					futures::Poll::Ready(()) => true,
					futures::Poll::Pending => false,
				}
			} else {
				false
			};

			if completed_on_open {
				made_progress_this_loop_iter = true;
				this.on_open_fut = None;
			}
		}match this.method_futures.poll_next_unpin(lw) {
			futures::Poll::Ready(Some(())) => made_progress_this_loop_iter = true,
			_ => {},
		}

		match this.inner.channel().recv_from(&mut this.msg_buf, lw) {
			futures::Poll::Ready(Ok(())) => {},
			futures::Poll::Pending => {
				if !made_progress_this_loop_iter {
					return futures::Poll::Pending;
				} else {
					continue;
				}
			}
			futures::Poll::Ready(Err(zx::Status::PEER_CLOSED)) => {
				return futures::Poll::Ready(Ok(()));
			}
			futures::Poll::Ready(Err(e)) =>
				return futures::Poll::Ready(Err(fidl::Error::ServerRequestRead(e))),
		}

		{
			// A message has been received from the channel
			let (bytes, handles) = this.msg_buf.split_mut();
			let (header, body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

			match header.ordinal {
					1061382220 | 1 => {
						let mut req: () = fidl::encoding::Decodable::new_empty();
						fidl::encoding::Decoder::decode_into(body_bytes, handles, &mut req)?;
						let control_handle = InterfaceControlHandle {
							inner: this.inner.clone(),
						};
						this.method_futures.push(
							this.server.method(control_handle)
						);
					}
				// TODO(cramertj) handle control/fileio messages
				_ => return futures::Poll::Ready(Err(fidl::Error::UnknownOrdinal {
					ordinal: header.ordinal,
					service_name: "unknown fidl", // TODO(cramertj)
				})),
			}
		}
		this.msg_buf.clear();
	}}
}

/// A Stream of incoming requests for Interface
pub struct InterfaceRequestStream {
	inner: ::std::sync::Arc<fidl::ServeInner>,
	msg_buf: Option<zx::MessageBuf>,
}

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

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

impl fidl::endpoints::RequestStream for InterfaceRequestStream {
	/// Consume a channel to make a InterfaceRequestStream
	fn from_channel(channel: ::fuchsia_async::Channel) -> Self {
		Self {
			inner: ::std::sync::Arc::new(fidl::ServeInner::new(channel)),
			msg_buf: Some(zx::MessageBuf::new()),
		}
	}

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

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

	fn into_inner(self) -> (::std::sync::Arc<fidl::ServeInner>, Option<zx::MessageBuf>) {
		(self.inner, self.msg_buf)
	}

	fn from_inner(inner: ::std::sync::Arc<fidl::ServeInner>, msg_buf: Option<zx::MessageBuf>) -> Self {
		Self { inner, msg_buf }
	}
}

impl Stream for InterfaceRequestStream {
	type Item = Result<InterfaceRequest, fidl::Error>;

	fn poll_next(mut self: ::std::pin::Pin<&mut Self>, lw: &::futures::task::LocalWaker)
		-> ::futures::Poll<Option<Self::Item>>
	{
		let this = &mut *self;
		if this.inner.poll_shutdown(lw) {
			this.msg_buf = None;
			return futures::Poll::Ready(None);
		}
		let msg_buf = this.msg_buf.as_mut()
								.expect("polled InterfaceRequestStream after completion");
		match this.inner.channel().recv_from(msg_buf, lw) {
			futures::Poll::Ready(Ok(())) => {},
			futures::Poll::Pending => return futures::Poll::Pending,
			futures::Poll::Ready(Err(zx::Status::PEER_CLOSED)) => {
				this.msg_buf = None;
				return futures::Poll::Ready(None)
			},
			futures::Poll::Ready(Err(e)) =>
				return futures::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(e)))),
		}

		let res = {
			// A message has been received from the channel
			let (bytes, handles) = msg_buf.split_mut();
			let (header, body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;

			match header.ordinal {
				1061382220 | 1 => {
					let mut req: () = fidl::encoding::Decodable::new_empty();
					fidl::encoding::Decoder::decode_into(body_bytes, handles, &mut req)?;
					let control_handle = InterfaceControlHandle {
						inner: this.inner.clone(),
					};

					InterfaceRequest::Method {control_handle,}
				}
				_ => return futures::Poll::Ready(Some(Err(fidl::Error::UnknownOrdinal {
					ordinal: header.ordinal,
					service_name: <InterfaceMarker as fidl::endpoints::ServiceMarker>::NAME,
				}))),
			}
		};

		msg_buf.clear();
		futures::Poll::Ready(Some(Ok(res)))
	}
}
/// interface comment #1
///
/// interface comment #3
pub enum InterfaceRequest {
	/// method comment #1
	///
	/// method comment #3
	Method {
		control_handle: InterfaceControlHandle,},
}

#[deprecated(note = "use InterfaceRequestStream instead")]
pub struct InterfaceImpl<
	State,
OnOpen: FnMut(&mut State, InterfaceControlHandle) -> OnOpenFut,
OnOpenFut: Future<Output = ()> + Send,
	Method: FnMut(&mut State,InterfaceControlHandle) -> MethodFut,
	MethodFut: Future<Output = ()> + Send,
> {
	pub state: State,
	pub on_open: OnOpen,
	pub method: Method,
}

// Unpin is never projected for the Impl struct
impl<
	State,
OnOpen: FnMut(&mut State, InterfaceControlHandle) -> OnOpenFut,
OnOpenFut: Future<Output = ()> + Send,
	Method: FnMut(&mut State,InterfaceControlHandle) -> MethodFut,
	MethodFut: Future<Output = ()> + Send,
> ::std::marker::Unpin for InterfaceImpl<State, OnOpen, OnOpenFut,
	Method,
	MethodFut,
>
{}

impl<
	State,
OnOpen: FnMut(&mut State, InterfaceControlHandle) -> OnOpenFut,
OnOpenFut: Future<Output = ()> + Send,
	Method: FnMut(&mut State,InterfaceControlHandle) -> MethodFut,
	MethodFut: Future<Output = ()> + Send,
> Interface for InterfaceImpl<State, OnOpen, OnOpenFut,
	Method,
	MethodFut,
>
{
	type OnOpenFut = OnOpenFut;
	fn on_open(&mut self, response_chan: InterfaceControlHandle) -> Self::OnOpenFut {
		(self.on_open)(&mut self.state, response_chan)
	}
	type MethodFut = MethodFut;
	fn method (&mut self,
		response_chan: InterfaceControlHandle
	) -> Self::MethodFut
	{
		(self.method)(
			&mut self.state,
			response_chan
		)
	}
	
}

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

impl Deref for InterfaceControlHandle {
        type Target = ::std::sync::Arc<fidl::ServeInner>;

	fn deref(&self) -> &Self::Target {
		&self.inner
	}
}


impl InterfaceControlHandle {
	pub fn shutdown(&self) {
		self.inner.shutdown()
	}}

/* beginning of response types */
