use std::collections::VecDeque; use std::fmt; use std::net::SocketAddr; use either::Either; use crate::error::ConnectError; /// Connect request #[derive(Eq, PartialEq, Debug, Hash)] pub enum Connect { /// Host name Host { host: String, port: u16 }, /// Host name with address of this host Addr { host: String, addr: Either>, }, } impl Connect { /// Create new `Connect` instance. pub fn new>(host: T, port: u16) -> Connect { Connect::Host { host: host.as_ref().to_owned(), port, } } /// Create `Connect` instance by spliting the string by ':' and convert the second part to u16 pub fn with>(host: T) -> Result { let mut parts_iter = host.as_ref().splitn(2, ':'); let host = parts_iter.next().ok_or(ConnectError::InvalidInput)?; let port_str = parts_iter.next().unwrap_or(""); let port = port_str .parse::() .map_err(|_| ConnectError::InvalidInput)?; Ok(Connect::Host { host: host.to_owned(), port, }) } /// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages. pub fn with_address>(host: T, addr: SocketAddr) -> Connect { Connect::Addr { addr: Either::Left(addr), host: host.into(), } } /// Host name fn host(&self) -> &str { match self { Connect::Host { ref host, .. } => host, Connect::Addr { ref host, .. } => host, } } } impl fmt::Display for Connect { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}:{}", self.host(), 0) } } pub struct Stream { io: T, host: String, params: P, } impl Stream { pub fn new(io: T, host: String) -> Self { Self { io, host, params: (), } } } impl Stream { /// Reconstruct from a parts. pub fn from_parts(io: T, host: String, params: P) -> Self { Self { io, params, host } } /// Deconstruct into a parts. pub fn into_parts(self) -> (T, String, P) { (self.io, self.host, self.params) } /// Replace inclosed object, return new Stream and old object pub fn replace(self, io: U) -> (T, Stream) { ( self.io, Stream { io, host: self.host, params: self.params, }, ) } /// Returns a shared reference to the underlying stream. pub fn get_ref(&self) -> &T { &self.io } /// Returns a mutable reference to the underlying stream. pub fn get_mut(&mut self) -> &mut T { &mut self.io } /// Get host name pub fn host(&self) -> &str { &self.host } /// Return new Io object with new parameter. pub fn set(self, params: U) -> Stream { Stream { io: self.io, host: self.host, params: params, } } /// Maps an Io<_, P> to Io<_, U> by applying a function to a contained value. pub fn map(self, op: F) -> Stream where F: FnOnce(P) -> U, { Stream { io: self.io, host: self.host, params: op(self.params), } } } impl std::ops::Deref for Stream { type Target = T; fn deref(&self) -> &T { &self.io } } impl std::ops::DerefMut for Stream { fn deref_mut(&mut self) -> &mut T { &mut self.io } } impl fmt::Debug for Stream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Stream {{{:?}}}", self.io) } }