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>>,
pub use_tls: Option<bool>,
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)
}
}
}