tropocol 0.1.2

Send and receive serde-compatible objects over TCP (async)
Documentation
//! Send and receive serde-compatible objects over TCP (async)
//!
//! With the `log` feature (enabled by default), the following events will be logged:
//!
//! - clean disconnects (`DEBUG`)
//! - dirty disconnects (`ERROR`)
//! - codec/serde errors (`ERROR`)
//! - message reception/emission (`TRACE`)
//!
//! # Roadmap
//!
//! - [x] async-fifo support
//! - [x] async-channel support
//! - [x] logging
//! - [ ] compression (gzip, lz4, lzma)
//! - [ ] other encodings (CBOR, BSON, MessagePack)
//!
//! # Example
//!
//! ```rust
//! let addr = ("127.0.0.1", 9000);
//! let stream = std::net::TcpStream::connect(addr).unwrap();
//! let stream = async_net::TcpStream::try_from(stream).unwrap();
//!
//! type Incoming = String;
//! type Outgoing = u32;
//!
//! let (task, tx, mut rx) = tropocol::async_fifo::session::<Outgoing, Incoming>(stream);
//! // spawn this task in an asynchronous executor
//!
//! tx.send(0u32 as Outgoing);
//!
//! async {
//!     let s: Incoming = rx.recv().await.unwrap();
//! };
//!
//! ```
//!

use futures_lite::{AsyncWriteExt, AsyncReadExt};
use futures_lite::future::or;
use std::future::Future;
use async_net::TcpStream;
use std::fmt;

use serde::{Serialize, Deserialize};

pub use async_net;

/// Underlying Session Task
pub mod raw;

#[cfg(feature = "async-fifo")]
pub mod async_fifo;

#[cfg(feature = "async-channel")]
pub mod async_channel;

/// Alias trait for `Send` futures
pub trait SendFut<O>: Future<Output = O> + Send {}
impl<O, Y: Future<Output = O> + Send> SendFut<O> for Y {}

/// Object which produces outgoing messages
pub trait GetOutgoing<O> {
    fn get_outgoing(&mut self) -> impl SendFut<Option<O>>;
}

/// Object which handles incoming messages
pub trait HandleIncoming<I> {
    fn handle_incoming(&mut self, incoming: I) -> impl SendFut<()>;
}

pub use traits::{Incoming, Outgoing};

#[cfg(feature = "log")]
mod traits {
    use core::fmt::Debug;
    use super::*;

    /// Trait for incoming objects
    pub trait Incoming: for<'a> Deserialize<'a> + Debug {}
    impl<I: for<'a> Deserialize<'a> + Debug> Incoming for I {}

    /// Trait for outgoing objects
    pub trait Outgoing: Serialize + Debug {}
    impl<O: Serialize + Debug> Outgoing for O {}
}

#[cfg(not(feature = "log"))]
mod traits {
    use super::*;

    /// Trait for incoming objects
    pub trait Incoming: for<'a> Deserialize<'a> {}
    impl<I: for<'a> Deserialize<'a>> Incoming for I {}

    /// Trait for outgoing objects
    pub trait Outgoing: Serialize {}
    impl<O: Serialize> Outgoing for O {}
}

#[derive(Debug)]
pub enum Error {
    UnexpectedEof,
    Codec(serde_json::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::UnexpectedEof => write!(f, "Error is here!"),
            Self::Codec(serde) => serde.fmt(f),
        }
    }
}

impl core::error::Error for Error {}