axol 0.2.0

Axol Web Framework
use std::{ops::Deref, sync::Arc};

use anyhow::anyhow;
use axol_http::{extensions::Removed, request::RequestPartsRef, response::ResponsePartsRef};

use crate::{Error, FromRequestParts, IntoResponseParts, Result};

#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct Extension<T>(pub T);

#[async_trait::async_trait]
impl<'a, T: Send + Sync + Clone + 'static> FromRequestParts<'a> for Extension<T> {
    async fn from_request_parts(request: RequestPartsRef<'a>) -> Result<Self> {
        Ok(Self(
            request
                .extensions
                .get::<T>()
                .ok_or_else(|| Error::internal(anyhow!("missing request extension")))?
                .clone(),
        ))
    }
}

impl<T> Deref for Extension<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Debug, Clone)]
#[must_use]
pub struct ExtensionArc<T>(pub Arc<T>);

#[async_trait::async_trait]
impl<'a, T: Send + Sync + Clone + 'static> FromRequestParts<'a> for ExtensionArc<T> {
    async fn from_request_parts(request: RequestPartsRef<'a>) -> Result<Self> {
        Ok(Self(
            request
                .extensions
                .get_arc::<T>()
                .ok_or_else(|| Error::internal(anyhow!("missing request extension")))?
                .clone(),
        ))
    }
}

impl<T> Deref for ExtensionArc<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Debug, Clone)]
#[must_use]
pub struct ExtensionRemove<T>(pub Removed<T>);

#[async_trait::async_trait]
impl<'a, T: Send + Sync + Clone + 'static> FromRequestParts<'a> for ExtensionRemove<T> {
    async fn from_request_parts(request: RequestPartsRef<'a>) -> Result<Self> {
        Ok(Self(
            request
                .extensions
                .remove::<T>()
                .ok_or_else(|| Error::internal(anyhow!("missing request extension")))?
                .clone(),
        ))
    }
}

#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct AddExtension<T>(pub T);

impl<T: Send + Sync + 'static> IntoResponseParts for AddExtension<T> {
    fn into_response_parts(self, response: &mut ResponsePartsRef<'_>) -> Result<()> {
        response.extensions.insert(self.0);
        Ok(())
    }
}