use std::sync::Arc;
use std::sync::OnceLock;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::time::Duration;
use arc_swap::ArcSwap;
use http::Method;
#[cfg(any(feature = "plugins", feature = "utoipa", feature = "vespera"))]
use parking_lot::RwLock;
use crate::extractors::json::SimdJsonMode;
use crate::handler::BoxHandler;
#[cfg(any(feature = "utoipa", feature = "vespera"))]
use crate::openapi::RouteOpenApi;
#[cfg(feature = "plugins")]
use crate::plugins::TakoPlugin;
#[cfg(feature = "signals")]
use crate::signals::SignalArbiter;
use crate::types::BoxMiddleware;
#[doc(alias = "route")]
pub struct Route {
pub path: String,
pub method: Method,
pub(crate) handler: BoxHandler,
pub(crate) middlewares: ArcSwap<Vec<BoxMiddleware>>,
pub(crate) has_middleware: AtomicBool,
pub tsr: bool,
#[cfg(feature = "plugins")]
pub(crate) plugins: RwLock<Vec<Box<dyn TakoPlugin>>>,
#[cfg(feature = "plugins")]
pub(crate) plugins_initialized: AtomicBool,
pub(crate) http_protocol: OnceLock<http::Version>,
#[cfg(feature = "signals")]
pub(crate) signals: SignalArbiter,
#[cfg(any(feature = "utoipa", feature = "vespera"))]
pub(crate) openapi: RwLock<Option<RouteOpenApi>>,
pub(crate) timeout: OnceLock<Duration>,
pub(crate) simd_json_mode: OnceLock<SimdJsonMode>,
}
impl Route {
pub fn new(path: String, method: Method, handler: BoxHandler, tsr: Option<bool>) -> Self {
Self {
path,
method,
handler,
middlewares: ArcSwap::new(Arc::default()),
has_middleware: AtomicBool::new(false),
tsr: tsr.unwrap_or(false),
#[cfg(feature = "plugins")]
plugins: RwLock::new(Vec::new()),
#[cfg(feature = "plugins")]
plugins_initialized: AtomicBool::new(false),
http_protocol: OnceLock::new(),
#[cfg(feature = "signals")]
signals: SignalArbiter::new(),
#[cfg(any(feature = "utoipa", feature = "vespera"))]
openapi: RwLock::new(None),
timeout: OnceLock::new(),
simd_json_mode: OnceLock::new(),
}
}
pub(crate) fn cloned_with_path(&self, new_path: String) -> Arc<Route> {
let cloned = Self {
path: new_path,
method: self.method.clone(),
handler: self.handler.clone(),
middlewares: ArcSwap::new(self.middlewares.load_full()),
has_middleware: AtomicBool::new(self.has_middleware.load(Ordering::Acquire)),
tsr: self.tsr,
#[cfg(feature = "plugins")]
plugins: RwLock::new(Vec::new()),
#[cfg(feature = "plugins")]
plugins_initialized: AtomicBool::new(true),
http_protocol: {
let lock = OnceLock::new();
if let Some(v) = self.http_protocol.get() {
let _ = lock.set(*v);
}
lock
},
#[cfg(feature = "signals")]
signals: self.signals.clone(),
#[cfg(any(feature = "utoipa", feature = "vespera"))]
openapi: RwLock::new(self.openapi.read().clone()),
timeout: {
let lock = OnceLock::new();
if let Some(v) = self.timeout.get() {
let _ = lock.set(*v);
}
lock
},
simd_json_mode: {
let lock = OnceLock::new();
if let Some(v) = self.simd_json_mode.get() {
let _ = lock.set(*v);
}
lock
},
};
Arc::new(cloned)
}
}