quokka-handler 0.3.0-beta.0

Handler helpers for Quokka
Documentation
use axum::response::IntoResponse;

#[derive(Clone)]
pub struct Error {
    pub debug: String,
    pub message: String,
}

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    pub fn new(message: impl ToString) -> Self {
        Self {
            message: message.to_string(),
            debug: message.to_string(),
        }
    }

    ///
    /// Wraps any printable error, with the debug output in the debug field
    ///
    /// # Tests
    ///
    /// ```
    /// let error = quokka_handler::Error::wrap("A test error")(quokka_handler::Error::new("Test Error"));
    /// let message = format!("{}", error);
    /// let debug = format!("{:?}", error);
    ///
    /// assert_eq!(message, "A test error");
    /// assert_eq!(debug, "Test Error");
    /// ```
    ///
    #[tracing::instrument(skip(message))]
    pub fn wrap<E: std::error::Error>(message: impl ToString) -> impl FnOnce(E) -> Self {
        let message = message.to_string();

        move |error| Self {
            message,
            debug: format!("{error:?}"),
        }
    }

    ///
    /// Wraps any printable error, with the debug output in the debug field
    ///
    /// # Tests
    ///
    /// ```
    /// #[tokio::main]
    /// async fn main() {
    /// let error = quokka_handler::Error::wrap_response(String::from("A test error")).await;
    /// let message = format!("{}", error);
    ///
    /// assert_eq!(message, "A test error");
    /// }
    /// ```
    ///
    #[tracing::instrument(skip(response))]
    pub async fn wrap_response(response: impl IntoResponse) -> Self {
        let error = axum::body::to_bytes(response.into_response().into_body(), 1024)
            .await
            .map(|bytes| String::from_utf8_lossy(&bytes).to_string())
            .map_err(Self::wrap("Unable to get response body to string"))
            .map(Self::new);

        match error {
            Ok(err) => err,
            Err(err) => err,
        }
    }
}

impl std::error::Error for Error {}

///
/// # Tests
///
/// ```
/// let error = format!("{:?}", quokka_handler::Error { message: String::new(), debug: String::from("Test Debug") });
///
/// assert_eq!(error, "Test Debug");
/// ```
///
impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(&self.message)
    }
}

///
/// # Tests
///
/// ```
/// let error = format!("{}", quokka_handler::Error::new("Test Error"));
///
/// assert_eq!(error, "Test Error");
/// ```
///
impl std::fmt::Debug for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(&self.debug)
    }
}

impl From<quokka_templating::Error> for Error {
    fn from(value: quokka_templating::Error) -> Self {
        Self {
            debug: format!("{value:?}"),
            message: value.to_string(),
        }
    }
}