chateau 0.3.2

Tower primitives for Servers and Clients with ergonomic APIs
Documentation
//! Client connection types.
//!
//! A client connection is composed of a transport, which produces a stream, and a protocol, which produces
//! a connection, which each serve a different purpose in the client connection lifecycle.
//!
//! ## Transport
//!
//! The transport is responsible for establishing a connection to a remote server, shuffling bytes back
//! and forth, and handling the low-level details of the connection. Transports implement the [`Transport`]
//! trait, effecitively making them a service which accepts an address and returns a bidirectional stream.
//!
//! Two builtin transports are provided:
//! - [`transport::tcp::TcpTransport`]: Connects to a remote server over TCP/IP. This is the default transport, and what
//!   usually powers things like HTTP connections.
//! - [`transport::duplex::DuplexTransport`]: Connects to a remote server over a duplex stream, which
//!   is an in-memory stream that can be used for testing or other purposes.
//!
//! ## Stream
//!
//! The stream is a bidirectional stream of bytes, which is used to send and receive data over the connection.
//! The stream is a low-level abstraction, and is used by the transport to send and receive data.
//!
//! ## Protocol
//!
//! The protocol is responsible for encoding and decoding request and response objects.
//!
//! Protocols implement the [`Protocol`] trait, which is a service that accepts an IO stream and
//! returns a connection. The connection is responsible for sending and receiving requests and responses.
//!
//! ## Connection
//!
//! The connection is responsible for sending and receiving requests and responses. It is the highest
//! level of abstraction in the client connection stack, and is the  part of the stack which accepts requests.
//!
//! Connections implement the [`Connection`] trait, which is a service that accepts a request and returns a
//! future which resolves to a response. The connection is responsible for encoding and decoding the request
//! and response objects, and for sending and receiving the data over the transport.

pub mod connection;
pub mod connector;
pub mod dns;
pub mod protocol;
pub mod service;
pub mod stream;
pub mod transport;

use thiserror::Error;

pub use self::connection::Connection;
pub use self::connector::Connector;
pub use self::protocol::Protocol;
#[cfg(feature = "tls")]
pub use self::transport::TlsTransport;
pub use self::transport::Transport;
pub use self::transport::TransportExt;

use super::pool::KeyError;

/// Error that can occur during the connection and serving process.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ConnectionError<T, P, S> {
    /// Error occurred during the connection
    #[error("creating connection")]
    Connecting(#[source] T),

    /// Error occurred during the handshake
    #[error("handshaking connection")]
    Handshaking(#[source] P),

    /// Error occurred during the service
    #[error("service: {0}")]
    Service(#[source] S),

    /// Connection can't even be attempted
    #[error("connection closed")]
    Unavailable,

    /// Error returned when building a key
    #[error("key error: {0}")]
    Key(#[from] KeyError),
}

impl<T, P, S> From<connector::Error<T, P>> for ConnectionError<T, P, S> {
    fn from(value: connector::Error<T, P>) -> Self {
        match value {
            connector::Error::Connecting(t) => ConnectionError::Connecting(t),
            connector::Error::Handshaking(p) => ConnectionError::Handshaking(p),
            connector::Error::Unavailable => ConnectionError::Unavailable,
        }
    }
}