net-relay 0.1.3

A set of types for network relay.
Documentation
use crate::error::Error;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;

pub struct Parts<P, F> {
    /// 监听地址
    pub bind_addrs: Vec<SocketAddr>,
    /// 连接池
    pub pools: Vec<Arc<P>>,
    /// 服务处理器
    pub relay_fn: Option<Arc<F>>,
    /// 是否使用tls, only for https
    pub use_tls: Option<bool>,
    /// 最大并发流, only for http2
    pub max_streams: Option<u32>,
}

pub struct Builder<P, F> {
    inner: Result<Parts<P, F>, Error>,
}

impl<P, F> Builder<P, F> {
    pub fn new() -> Self {
        Builder {
            inner: Ok(Parts {
                bind_addrs: Vec::new(),
                pools: vec![],
                relay_fn: None,
                use_tls: None,
                max_streams: None,
            }),
        }
    }

    pub fn pool(self, p: P) -> Self {
        Builder {
            inner: self.inner.and_then(move |mut inner| {
                inner.pools.push(Arc::new(p));
                Ok(inner)
            }),
        }
    }

    pub fn relay_fn(self, f: F) -> Self {
        Builder {
            inner: self.inner.and_then(move |mut inner| {
                inner.relay_fn = Some(Arc::new(f));
                Ok(inner)
            }),
        }
    }

    pub fn bind<A: ToSocketAddrs>(self, addr: A) -> Self {
        Builder {
            inner: self.inner.and_then(move |mut inner| {
                let addrs: Vec<SocketAddr> = addr.to_socket_addrs()?.collect();
                inner.bind_addrs = addrs;
                Ok(inner)
            }),
        }
    }

    pub fn max_streams(self, max: Option<u32>) -> Self {
        Builder {
            inner: self.inner.and_then(move |mut inner| {
                inner.max_streams = max;
                Ok(inner)
            }),
        }
    }

    pub fn build(self) -> Result<Parts<P, F>, Error> {
        let parts = self.inner?;
        if parts.pools.is_empty() {
            Err(Error::NoPool)
        } else if parts.relay_fn.is_none() {
            Err(Error::NoRelayFn)
        } else if parts.bind_addrs.is_empty() {
            Err(Error::NoBindAddress)
        } else {
            Ok(parts)
        }
    }
    
    pub fn build_without_pool(self) -> Result<Parts<P, F>, Error> {
        let parts = self.inner?;
        if parts.bind_addrs.is_empty() {
            Err(Error::NoBindAddress)
        } else if parts.relay_fn.is_none() {
            Err(Error::NoRelayFn)
        } else {
            Ok(parts)
        }
    }
}