use crate::Runtime;
use async_cell::sync::AsyncCell;
use std::{cell::OnceCell, future::IntoFuture, net::SocketAddr, sync::Arc};
use swansong::{ShutdownCompletion, Swansong};
use trillium_http::HttpContext;
#[derive(Clone, Debug)]
pub struct ServerHandle {
pub(crate) swansong: Swansong,
pub(crate) context: Arc<AsyncCell<Arc<HttpContext>>>,
pub(crate) received_context: OnceCell<Arc<HttpContext>>,
pub(crate) runtime: Runtime,
}
#[derive(Debug)]
pub struct BoundInfo(Arc<HttpContext>);
impl BoundInfo {
pub fn shared_state<T: Send + Sync + 'static>(&self) -> Option<&T> {
self.0.shared_state().get()
}
pub fn tcp_socket_addr(&self) -> Option<&SocketAddr> {
self.shared_state()
}
pub fn url(&self) -> Option<&url::Url> {
self.shared_state()
}
#[cfg(unix)]
pub fn unix_socket_addr(&self) -> Option<&std::os::unix::net::SocketAddr> {
self.shared_state()
}
pub fn context(&self) -> Arc<HttpContext> {
self.0.clone()
}
}
impl ServerHandle {
pub async fn info(&self) -> BoundInfo {
if let Some(context) = self.received_context.get().cloned() {
return BoundInfo(context);
}
let arc_context = self.context.get().await;
let context = self.received_context.get_or_init(|| arc_context);
BoundInfo(Arc::clone(context))
}
pub fn shut_down(&self) -> ShutdownCompletion {
self.swansong.shut_down()
}
pub fn swansong(&self) -> Swansong {
self.swansong.clone()
}
pub fn runtime(&self) -> Runtime {
self.runtime.clone()
}
}
impl IntoFuture for ServerHandle {
type IntoFuture = ShutdownCompletion;
type Output = ();
fn into_future(self) -> Self::IntoFuture {
self.swansong.into_future()
}
}