use std::collections::VecDeque; use std::fmt; use std::net::SocketAddr; use either::Either; /// Connect request pub trait Address { /// Host name of the request fn host(&self) -> &str; /// Port of the request fn port(&self) -> Option; } impl Address for String { fn host(&self) -> &str { &self } fn port(&self) -> Option { None } } impl Address for &'static str { fn host(&self) -> &str { self } fn port(&self) -> Option { None } } /// Connect request #[derive(Eq, PartialEq, Debug, Hash)] pub struct Connect { pub(crate) req: T, pub(crate) port: u16, pub(crate) addr: Option>>, } impl Connect { /// Create `Connect` instance by spliting the string by ':' and convert the second part to u16 pub fn new(req: T) -> Connect { let (_, port) = parse(req.host()); Connect { req, port: port.unwrap_or(0), addr: None, } } /// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages. pub fn with(req: T, addr: SocketAddr) -> Connect { Connect { req, port: 0, addr: Some(Either::Left(addr)), } } /// Host name pub fn host(&self) -> &str { self.req.host() } /// Port of the request pub fn port(&self) -> u16 { self.req.port().unwrap_or(self.port) } } impl From for Connect { fn from(addr: T) -> Self { Connect::new(addr) } } impl fmt::Display for Connect { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}:{}", self.host(), self.port()) } } fn parse(host: &str) -> (&str, Option) { let mut parts_iter = host.splitn(2, ':'); if let Some(host) = parts_iter.next() { let port_str = parts_iter.next().unwrap_or(""); if let Ok(port) = port_str.parse::() { (host, Some(port)) } else { (host, None) } } else { (host, None) } } pub struct Connection { io: U, req: T, } impl Connection { pub fn new(io: U, req: T) -> Self { Self { io, req } } } impl Connection { /// Reconstruct from a parts. pub fn from_parts(io: U, req: T) -> Self { Self { io, req } } /// Deconstruct into a parts. pub fn into_parts(self) -> (U, T) { (self.io, self.req) } /// Replace inclosed object, return new Stream and old object pub fn replace(self, io: Y) -> (U, Connection) { (self.io, Connection { io, req: self.req }) } /// Returns a shared reference to the underlying stream. pub fn get_ref(&self) -> &U { &self.io } /// Returns a mutable reference to the underlying stream. pub fn get_mut(&mut self) -> &mut U { &mut self.io } } impl Connection { /// Get request pub fn host(&self) -> &str { &self.req.host() } } impl std::ops::Deref for Connection { type Target = U; fn deref(&self) -> &U { &self.io } } impl std::ops::DerefMut for Connection { fn deref_mut(&mut self) -> &mut U { &mut self.io } } impl fmt::Debug for Connection { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Stream {{{:?}}}", self.io) } }