skyzen_core/
lib.rs

1#![deny(unsafe_code)]
2#![cfg_attr(not(feature = "std"), no_std)]
3//! Base type and trait for HTTP server.
4
5extern crate alloc;
6#[cfg(feature = "std")]
7extern crate std;
8
9#[macro_use]
10mod macros;
11
12mod extract;
13pub use extract::Extractor;
14mod responder;
15pub use responder::Responder;
16mod server;
17pub use server::Server;
18#[cfg(feature = "openapi")]
19pub mod openapi;
20
21pub use http_kit::{
22    endpoint, header, method, middleware, uri, version, Body, BodyError, Endpoint, Extensions,
23    Method, Middleware, Request, Response, Result, ResultExt, StatusCode, Uri, Version,
24};
25
26/// Error types used in skyzen.
27pub mod error {
28    use std::fmt::{Debug, Display};
29
30    // Since `error[E0119]`, we have to wrap `http-kit`'s `Error` here.
31    pub use http_kit::error::{BoxHttpError, HttpError};
32
33    use http_kit::{Error as HttpKitError, StatusCode};
34
35    /// A concrete error type for HTTP operations.
36    pub struct Error(http_kit::error::Error);
37
38    impl Debug for Error {
39        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40            Debug::fmt(&self.0, f)
41        }
42    }
43
44    impl Display for Error {
45        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46            Display::fmt(&self.0, f)
47        }
48    }
49
50    impl Error {
51        /// Create a new error from any standard error type.
52        pub fn new(e: impl Into<eyre::Report>) -> Self {
53            Self(HttpKitError::new(e))
54        }
55
56        /// Create a new error with a custom message.
57        pub fn msg(msg: impl Display + Send + Sync + Debug + 'static) -> Self {
58            Self(HttpKitError::msg(msg))
59        }
60
61        /// Consume the error and return the inner `eyre::Report`.
62        pub fn into_inner(self) -> eyre::Report {
63            self.0.into_inner()
64        }
65
66        /// Convert this error into a boxed HTTP error trait object.
67        #[must_use]
68        pub fn into_boxed_http_error(self) -> BoxHttpError {
69            self.0.into_boxed_http_error()
70        }
71
72        /// Set the HTTP status code for this error.
73        #[must_use]
74        pub fn set_status(self, status: StatusCode) -> Self {
75            Self(self.0.set_status(status))
76        }
77    }
78
79    impl<T> From<T> for Error
80    where
81        T: Into<HttpKitError>,
82    {
83        fn from(value: T) -> Self {
84            Self(value.into())
85        }
86    }
87
88    /// Result type used in skyzen.
89    pub type Result<T> = core::result::Result<T, Error>;
90
91    /// Extension trait for `Result` and `Option` to set HTTP status code on error.
92    #[allow(clippy::missing_errors_doc)]
93    pub trait ResultExt<T> {
94        /// Set the HTTP status code for this error.
95        fn status(self, status: StatusCode) -> Result<T>;
96    }
97
98    impl<T, E: Into<Error>> ResultExt<T> for core::result::Result<T, E> {
99        fn status(self, status: StatusCode) -> Result<T> {
100            self.map_err(|e| e.into().set_status(status))
101        }
102    }
103
104    impl<T> ResultExt<T> for core::option::Option<T> {
105        fn status(self, status: StatusCode) -> Result<T> {
106            self.ok_or_else(|| Error::msg("None").set_status(status))
107        }
108    }
109}
110
111pub use error::*;