use std::{
borrow::Cow,
fmt::{self, Display, Formatter},
net::SocketAddr,
ops::Deref,
sync::Arc,
};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ListenerKind {
Tcp(SocketAddr),
Quic(SocketAddr),
#[cfg(unix)]
Unix(Option<std::path::PathBuf>),
Other(Cow<'static, str>),
}
impl Display for ListenerKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Tcp(addr) | Self::Quic(addr) => Display::fmt(addr, f),
#[cfg(unix)]
Self::Unix(Some(path)) => Display::fmt(&path.display(), f),
#[cfg(unix)]
Self::Unix(None) => f.write_str("<unnamed unix socket>"),
Self::Other(descriptor) => f.write_str(descriptor),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Listener(Arc<Inner>);
#[derive(Debug, PartialEq, Eq)]
struct Inner {
kind: ListenerKind,
secure: bool,
}
impl Listener {
#[must_use]
pub fn new(kind: ListenerKind, secure: bool) -> Self {
Self(Arc::new(Inner { kind, secure }))
}
#[must_use]
pub fn tcp(addr: SocketAddr, secure: bool) -> Self {
Self::new(ListenerKind::Tcp(addr), secure)
}
#[must_use]
pub fn quic(addr: SocketAddr) -> Self {
Self::new(ListenerKind::Quic(addr), true)
}
#[cfg(unix)]
#[must_use]
pub fn unix(path: Option<std::path::PathBuf>, secure: bool) -> Self {
Self::new(ListenerKind::Unix(path), secure)
}
#[must_use]
pub fn kind(&self) -> &ListenerKind {
&self.0.kind
}
#[must_use]
pub fn is_secure(&self) -> bool {
self.0.secure
}
#[must_use]
pub fn socket_addr(&self) -> Option<SocketAddr> {
match self.0.kind {
ListenerKind::Tcp(addr) | ListenerKind::Quic(addr) => Some(addr),
_ => None,
}
}
#[must_use]
pub fn port(&self) -> Option<u16> {
self.socket_addr().map(|addr| addr.port())
}
}
impl Display for Listener {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match &self.0.kind {
ListenerKind::Tcp(addr) | ListenerKind::Quic(addr) => {
let scheme = if self.0.secure { "https" } else { "http" };
write!(f, "{scheme}://{addr}")
}
#[cfg(unix)]
ListenerKind::Unix(Some(path)) => write!(f, "unix:{}", path.display()),
#[cfg(unix)]
ListenerKind::Unix(None) => f.write_str("unix:<unnamed>"),
ListenerKind::Other(descriptor) => f.write_str(descriptor),
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Listeners(pub Vec<Listener>);
impl Deref for Listeners {
type Target = [Listener];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Listener>> for Listeners {
fn from(listeners: Vec<Listener>) -> Self {
Self(listeners)
}
}
impl FromIterator<Listener> for Listeners {
fn from_iter<T: IntoIterator<Item = Listener>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}