mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 17:57:47 +03:00
Добавлена возможность создания ResponseError с описанием ошибки.
Добавлен макрос для трансформации ErrorCode в Response, а также для имплементации треита PartialStatusCode.
This commit is contained in:
@@ -2,10 +2,9 @@ extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
mod response_error_message {
|
||||
use proc_macro::TokenStream;
|
||||
mod shared {
|
||||
use quote::{ToTokens, quote};
|
||||
use syn::Attribute;
|
||||
use syn::{Attribute, DeriveInput};
|
||||
|
||||
pub fn find_status_code(attrs: &Vec<Attribute>) -> Option<proc_macro2::TokenStream> {
|
||||
attrs
|
||||
@@ -31,7 +30,7 @@ mod response_error_message {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fmt(ast: &syn::DeriveInput) -> TokenStream {
|
||||
pub fn get_arms(ast: &DeriveInput) -> Vec<proc_macro2::TokenStream> {
|
||||
let name = &ast.ident;
|
||||
|
||||
let variants = if let syn::Data::Enum(data) = &ast.data {
|
||||
@@ -54,21 +53,56 @@ mod response_error_message {
|
||||
|
||||
if status_code_arms.len() < variants.len() {
|
||||
let status_code = find_status_code(&ast.attrs)
|
||||
.unwrap_or_else(|| quote! { actix_web::http::StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.unwrap_or_else(|| quote! { ::actix_web::http::StatusCode::INTERNAL_SERVER_ERROR });
|
||||
|
||||
status_code_arms.push(quote! { _ => #status_code });
|
||||
}
|
||||
|
||||
status_code_arms
|
||||
}
|
||||
}
|
||||
|
||||
mod response_error_message {
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn fmt(ast: &syn::DeriveInput) -> TokenStream {
|
||||
let name = &ast.ident;
|
||||
|
||||
let status_code_arms = super::shared::get_arms(ast);
|
||||
|
||||
TokenStream::from(quote! {
|
||||
impl actix_web::ResponseError for #name {
|
||||
fn status_code(&self) -> actix_web::http::StatusCode {
|
||||
impl ::actix_web::ResponseError for #name {
|
||||
fn status_code(&self) -> ::actix_web::http::StatusCode {
|
||||
match self {
|
||||
#(#status_code_arms)*
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> actix_web::HttpResponse<BoxBody> {
|
||||
actix_web::HttpResponse::build(self.status_code()).json(crate::utility::error::ResponseErrorMessage::new(self.clone()))
|
||||
fn error_response(&self) -> ::actix_web::HttpResponse<BoxBody> {
|
||||
::actix_web::HttpResponse::build(self.status_code())
|
||||
.json(crate::utility::error::ResponseErrorMessage::new(self.clone()))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod status_code {
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn fmt(ast: &syn::DeriveInput) -> TokenStream {
|
||||
let name = &ast.ident;
|
||||
|
||||
let status_code_arms = super::shared::get_arms(ast);
|
||||
|
||||
TokenStream::from(quote! {
|
||||
impl crate::routes::schema::PartialStatusCode for #name {
|
||||
fn status_code(&self) -> ::actix_web::http::StatusCode {
|
||||
match self {
|
||||
#(#status_code_arms)*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -85,13 +119,13 @@ mod responder_json {
|
||||
TokenStream::from(quote! {
|
||||
impl ::actix_web::Responder for #name {
|
||||
type Body = ::actix_web::body::EitherBody<::actix_web::body::BoxBody>;
|
||||
|
||||
|
||||
fn respond_to(self, _: &::actix_web::HttpRequest) -> ::actix_web::HttpResponse<Self::Body> {
|
||||
match ::serde_json::to_string(&self) {
|
||||
Ok(body) => ::actix_web::HttpResponse::Ok()
|
||||
.json(body)
|
||||
.map_into_left_body(),
|
||||
|
||||
|
||||
Err(err) => ::actix_web::HttpResponse::from_error(
|
||||
::actix_web::error::JsonPayloadError::Serialize(err),
|
||||
)
|
||||
@@ -103,7 +137,7 @@ mod responder_json {
|
||||
}
|
||||
}
|
||||
|
||||
mod into_iresponse {
|
||||
mod into_response_error {
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
@@ -111,17 +145,37 @@ mod into_iresponse {
|
||||
let name = &ast.ident;
|
||||
|
||||
TokenStream::from(quote! {
|
||||
impl<E> ::core::convert::Into<crate::routes::schema::IResponse<#name, E>> for #name
|
||||
where
|
||||
E: ::serde::ser::Serialize
|
||||
+ ::utoipa::PartialSchema
|
||||
+ ::core::clone::Clone
|
||||
+ crate::routes::schema::HttpStatusCode,
|
||||
{
|
||||
fn into(self) -> crate::routes::schema::IResponse<#name, E> {
|
||||
crate::routes::schema::IResponse(Ok(self))
|
||||
impl ::core::convert::Into<crate::routes::schema::ResponseError<#name>> for #name {
|
||||
fn into(self) -> crate::routes::schema::ResponseError<#name> {
|
||||
crate::routes::schema::ResponseError {
|
||||
code: self,
|
||||
message: ::core::option::Option::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::routes::schema::IntoResponseAsError<T> for #name
|
||||
where
|
||||
T: ::serde::ser::Serialize + ::utoipa::PartialSchema {}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fmt_named(ast: &syn::DeriveInput) -> TokenStream {
|
||||
let name = &ast.ident;
|
||||
|
||||
TokenStream::from(quote! {
|
||||
impl ::core::convert::Into<crate::routes::schema::ResponseError<#name>> for #name {
|
||||
fn into(self) -> crate::routes::schema::ResponseError<#name> {
|
||||
crate::routes::schema::ResponseError {
|
||||
message: ::core::option::Option::Some(format!("{}", self)),
|
||||
code: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::routes::schema::IntoResponseAsError<T> for #name
|
||||
where
|
||||
T: ::serde::ser::Serialize + ::utoipa::PartialSchema {}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -140,9 +194,23 @@ pub fn responser_json_derive(input: TokenStream) -> TokenStream {
|
||||
responder_json::fmt(&ast)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(IntoIResponse)]
|
||||
pub fn into_iresponse_derive(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(IntoResponseError)]
|
||||
pub fn into_response_error_derive(input: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse(input).unwrap();
|
||||
|
||||
into_iresponse::fmt(&ast)
|
||||
into_response_error::fmt(&ast)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(IntoResponseErrorNamed)]
|
||||
pub fn into_response_error_named_derive(input: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse(input).unwrap();
|
||||
|
||||
into_response_error::fmt_named(&ast)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(StatusCode, attributes(status_code))]
|
||||
pub fn status_code_derive(input: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse(input).unwrap();
|
||||
|
||||
status_code::fmt(&ast)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user