use futures::{failed, Future};
use futures::future::Either;
use {Method, Attribute, Error};
use message::{Indication, Request, RawMessage};
pub use self::base::BaseClient;
pub use self::udp::UdpClient;
pub use self::tcp::TcpClient;
pub mod futures {
pub use super::futures_impl::{Call, Cast};
pub use super::base::{BaseCallRaw, BaseCastRaw};
pub use super::udp::{UdpCallRaw, UdpCastRaw};
pub use super::tcp::{TcpCallRaw, TcpCastRaw, InitTcpClient};
}
mod base;
mod udp;
mod tcp;
pub trait Client {
type CallRaw: Future<Item = RawMessage, Error = Error>;
type CastRaw: Future<Item = (), Error = Error>;
fn call<M, A>(&mut self, message: Request<M, A>) -> futures::Call<M, A, Self::CallRaw>
where M: Method,
A: Attribute
{
match track_err!(RawMessage::try_from_request(message)) {
Err(e) => futures_impl::call(Either::A(failed(e))),
Ok(m) => futures_impl::call(Either::B(self.call_raw(m))),
}
}
fn cast<M, A>(&mut self, message: Indication<M, A>) -> futures::Cast<Self::CastRaw>
where M: Method,
A: Attribute
{
match track_err!(RawMessage::try_from_indication(message)) {
Err(e) => futures_impl::cast(Either::A(failed(e))),
Ok(m) => futures_impl::cast(Either::B(self.cast_raw(m))),
}
}
fn call_raw(&mut self, message: RawMessage) -> Self::CallRaw;
fn cast_raw(&mut self, message: RawMessage) -> Self::CastRaw;
}
mod futures_impl {
use std::fmt;
use std::marker::PhantomData;
use futures::{Future, Poll, Async};
use futures::future::{Either, Failed};
use {Method, Attribute, Error};
use message::{Response, RawMessage};
pub fn cast<F>(future: Either<Failed<(), Error>, F>) -> Cast<F> {
Cast(future)
}
pub struct Cast<F>(Either<Failed<(), Error>, F>);
impl<F> Future for Cast<F>
where F: Future<Item = (), Error = Error>
{
type Item = ();
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
track_err!(self.0.poll())
}
}
impl<F> fmt::Debug for Cast<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Either::A(_) => write!(f, "Cast(A(_))"),
Either::B(_) => write!(f, "Cast(B(_))"),
}
}
}
pub fn call<M, A, F>(future: Either<Failed<RawMessage, Error>, F>) -> Call<M, A, F> {
Call(future, PhantomData)
}
pub struct Call<M, A, F>(Either<Failed<RawMessage, Error>, F>, PhantomData<(M, A)>);
impl<M, A, F> Future for Call<M, A, F>
where M: Method,
A: Attribute,
F: Future<Item = RawMessage, Error = Error>
{
type Item = Response<M, A>;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::Ready(message) = track_try!(self.0.poll()) {
track_err!(message.try_into_response()).map(Async::Ready)
} else {
Ok(Async::NotReady)
}
}
}
impl<M, A, F> fmt::Debug for Call<M, A, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Either::A(_) => write!(f, "Call(A(_), _)"),
Either::B(_) => write!(f, "Call(B(_), _)"),
}
}
}
}