Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions packages/breach-macros/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,28 @@ impl<'a> ToTokens for HttpError<'a> {
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();

let status = self.data.status();
let hook = self.data.hook();

tokens.append_all(quote! {
#[automatically_derived]
impl #impl_generics ::breach::HttpError for #ident #type_generics #where_clause {
fn status(&self) -> ::breach::http::StatusCode {
#status
}

fn hook(&self) {
#hook
}
}
});

if let Some(attribute) = self.data.attribute() {
if attribute.axum {
let hook = attribute.axum_hook.as_ref().map(|hook| {
quote! {
#hook(&self);
}
});

tokens.append_all(quote! {
#[automatically_derived]
impl #impl_generics ::axum::response::IntoResponse for #ident #type_generics #where_clause {
fn into_response(self) -> ::axum::response::Response {
#hook;
self.hook();

(self.status(), ::axum::Json(self)).into_response()
}
Expand Down
24 changes: 17 additions & 7 deletions packages/breach-macros/src/http/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ impl<'a> HttpErrorAttribute {
pub struct HttpErrorDataAttribute {
pub status: Option<Status>,
pub base: Option<Type>,
pub hook: Option<Expr>,
pub axum: bool,
pub axum_hook: Option<Expr>,
pub utoipa: bool,
}

Expand Down Expand Up @@ -88,8 +88,8 @@ impl<'a> HttpErrorDataAttribute {
pub fn parse(attribute: &'a Attribute) -> Result<Self> {
let mut status = None;
let mut base = None;
let mut hook = None;
let mut axum = false;
let mut axum_hook = None;
let mut utoipa = false;

attribute.parse_nested_meta(|meta| {
Expand All @@ -101,12 +101,12 @@ impl<'a> HttpErrorDataAttribute {
base = Some(meta.value()?.parse()?);

Ok(())
} else if meta.path.is_ident("axum") {
axum = true;
} else if meta.path.is_ident("hook") {
hook = Some(meta.value()?.parse()?);

Ok(())
} else if meta.path.is_ident("axum_hook") {
axum_hook = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("axum") {
axum = true;

Ok(())
} else if meta.path.is_ident("utoipa") {
Expand All @@ -121,8 +121,8 @@ impl<'a> HttpErrorDataAttribute {
Ok(Self {
status,
base,
hook,
axum,
axum_hook,
utoipa,
})
}
Expand All @@ -134,6 +134,16 @@ impl<'a> HttpErrorDataAttribute {
pub fn responses(&self, r#type: Option<TokenStream>) -> TokenStream {
responses(self.status.as_ref(), r#type)
}

pub fn hook(&self) -> TokenStream {
if let Some(hook) = &self.hook {
quote! {
#hook(&self);
}
} else {
TokenStream::new()
}
}
}

fn status(status: Option<&Status>) -> TokenStream {
Expand Down
8 changes: 8 additions & 0 deletions packages/breach-macros/src/http/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ impl<'a> HttpErrorData<'a> {
HttpErrorData::Union(r#union) => r#union.responses(),
}
}

pub fn hook(&self) -> TokenStream {
match self {
HttpErrorData::Struct(r#struct) => r#struct.hook(),
HttpErrorData::Enum(r#enum) => r#enum.hook(),
HttpErrorData::Union(r#union) => r#union.hook(),
}
}
}
23 changes: 23 additions & 0 deletions packages/breach-macros/src/http/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ impl<'a> HttpErrorEnum<'a> {
}
}
}

pub fn hook(&self) -> TokenStream {
let hook = self.attribute.as_ref().map(|attribute| attribute.hook());
let arms = self.variants.iter().map(|variant| variant.hook());

quote! {
#hook

match &self {
#( #arms ), *
}
}
}
}

pub struct HttpErrorEnumVariant<'a> {
Expand Down Expand Up @@ -147,6 +160,16 @@ impl<'a> HttpErrorEnumVariant<'a> {
}
}

pub fn hook(&self) -> TokenStream {
self.arm(if self.attribute.is_none() && self.field.is_some() {
quote!({
value.hook();
})
} else {
quote!({})
})
}

fn arm(&self, tokens: TokenStream) -> TokenStream {
let enum_ident = self.enum_ident;
let ident = self.ident;
Expand Down
4 changes: 4 additions & 0 deletions packages/breach-macros/src/http/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ impl<'a> HttpErrorStruct {
pub fn responses(&self) -> TokenStream {
self.attribute.responses(Some(quote!(Self)))
}

pub fn hook(&self) -> TokenStream {
self.attribute.hook()
}
}
4 changes: 4 additions & 0 deletions packages/breach-macros/src/http/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ impl HttpErrorUnion {
pub fn responses(&self) -> TokenStream {
todo!()
}

pub fn hook(&self) -> TokenStream {
todo!()
}
}
3 changes: 3 additions & 0 deletions packages/breach/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ use http::StatusCode;
pub trait HttpError {
/// HTTP status code.
fn status(&self) -> StatusCode;

/// Hook called when the HTTP error is used as response.
fn hook(&self);
}