use crate::AletheiaDB;
use crate::http::error::AletheiaHttpError;
use axum::extract::FromRequestParts;
use axum::http::request::Parts;
use std::sync::Arc;
#[derive(Clone)]
pub struct AppState {
db: Arc<AletheiaDB>,
}
impl AppState {
#[must_use]
pub fn new(db: Arc<AletheiaDB>) -> Self {
Self { db }
}
#[must_use]
pub fn db(&self) -> &AletheiaDB {
&self.db
}
#[must_use]
pub fn db_arc(&self) -> Arc<AletheiaDB> {
self.db.clone()
}
}
impl From<Arc<AletheiaDB>> for AppState {
fn from(db: Arc<AletheiaDB>) -> Self {
Self::new(db)
}
}
impl FromRequestParts<autumn_web::prelude::AppState> for AppState {
type Rejection = AletheiaHttpError;
async fn from_request_parts(
_parts: &mut Parts,
state: &autumn_web::prelude::AppState,
) -> Result<Self, Self::Rejection> {
state
.extension::<AppState>()
.map(|arc| (*arc).clone())
.ok_or(AletheiaHttpError::StateMissing)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn app_state_clone_shares_db() {
let db = Arc::new(AletheiaDB::new().unwrap());
let state = AppState::new(db.clone());
let state2 = state.clone();
assert!(Arc::ptr_eq(&state.db_arc(), &state2.db_arc()));
}
#[test]
fn from_arc_db_works() {
let db = Arc::new(AletheiaDB::new().unwrap());
let state: AppState = db.clone().into();
assert!(Arc::ptr_eq(&db, &state.db_arc()));
}
}