use std::{error, fmt};
use lexa_syn::field;
use syn::__private::quote::{quote, quote_spanned};
use syn::__private::{Span, TokenStream, TokenStream2};
use syn::spanned::Spanned;
pub type ViewDeriveParserInput = syn::ItemStruct;
type Result<'err, T> = std::result::Result<T, ViewDeriveParserError>;
pub struct ViewDerive {
item_struct: ViewDeriveParserInput,
}
#[derive(Debug)]
pub struct ViewDeriveParserError {
span: syn::__private::Span,
kind: ErrorDeriveParserErrorKind,
}
#[derive(Debug)]
pub enum ErrorDeriveParserErrorKind {
IsNotNamedOrUnitStruct,
}
impl lexa_syn::Parser for ViewDerive {
type Err<'err> = ViewDeriveParserError;
type Input = ViewDeriveParserInput;
fn new(input: Self::Input) -> Self {
Self { item_struct: input }
}
fn analyze(&self) -> Result<'_, TokenStream> {
if !field::is_named_fields(&self.item_struct.fields)
&& !field::is_unit_fields(&self.item_struct.fields)
{
return Err(ViewDeriveParserError {
span: self.item_struct.span(),
kind: ErrorDeriveParserErrorKind::IsNotNamedOrUnitStruct,
});
}
let item_struct_name = &self.item_struct.ident;
let output = quote! {
impl lexa_framework::http::response::IntoResponse for #item_struct_name {
fn into_response(self) -> lexa_framework::http::response::Response {
use lexa_framework::view::ViewInterface;
lexa_framework::http::response::Html(
self.render().to_string()
).into_response()
}
}
impl From<#item_struct_name> for
lexa_framework::http::body::Full<
lexa_framework::http::body::Bytes
>
{
fn from(s: #item_struct_name) -> Self {
use lexa_framework::view::ViewInterface;
Self::from(s.render().to_string())
}
}
};
let output = <TokenStream2 as Into<TokenStream>>::into(output);
Ok(output)
}
}
impl<'err> lexa_syn::ParserError<'err> for ViewDeriveParserError {
fn compile_error(self) -> TokenStream {
let err_s = self.to_string();
let tokens = quote_spanned! {
self.span() => compile_error!(#err_s);
};
TokenStream::from(tokens)
}
fn span(self) -> Span {
self.span
}
}
impl error::Error for ViewDeriveParserError {}
impl fmt::Display for ViewDeriveParserError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let err_s = match self.kind {
| ErrorDeriveParserErrorKind::IsNotNamedOrUnitStruct => {
String::from(
"ne supporte que les structures de champs nommés ou les \
structures unitaires.",
)
}
};
write!(f, "#[derive(View)]: {}", err_s)
}
}