diff --git a/proc_macros/proc_macros.rs b/proc_macros/proc_macros.rs index 4e2a9e8..8b3d5bd 100644 --- a/proc_macros/proc_macros.rs +++ b/proc_macros/proc_macros.rs @@ -9,6 +9,7 @@ use syn::token; use syn::Block; use syn::Expr; use syn::Ident; +use syn::ItemEnum; use syn::ItemFn; use syn::Lit; use syn::LitBool; @@ -580,3 +581,42 @@ pub fn check_json_keys(item: TokenStream) -> TokenStream { ); stream.into() } + +#[proc_macro_derive(CheckUnkown)] +pub fn derive_check_unknown(item: TokenStream) -> TokenStream { + let ItemEnum { + attrs: _, + vis: _, + enum_token: _, + ident, + generics: _, + brace_token: _, + variants, + } = parse_macro_input!(item as ItemEnum); + let mut streams = Vec::new(); + for i in variants.iter() { + let ident = i.ident.clone(); + let s = ident.to_string(); + if s == "Unknown" { + streams.push( + quote!(Self::#ident(data) => Err(crate::fanbox::error::FanboxAPIError::from(format!( + "{} {}", + crate::gettext("Failed to recognize type:"), + data + ))),), + ); + } else { + streams.push(quote!(Self::#ident(tmp) => crate::fanbox::check::CheckUnkown::check_unknown(tmp),)); + } + } + let stream = quote!( + impl crate::fanbox::check::CheckUnkown for #ident { + fn check_unknown(&self) -> Result<(), crate::fanbox::error::FanboxAPIError> { + match self { + #(#streams)* + } + } + } + ); + stream.into() +} diff --git a/src/fanbox/article/block.rs b/src/fanbox/article/block.rs index 2bb7173..3f55fbe 100644 --- a/src/fanbox/article/block.rs +++ b/src/fanbox/article/block.rs @@ -1,4 +1,5 @@ use super::super::check::CheckUnkown; +use super::super::error::FanboxAPIError; use json::JsonValue; use proc_macros::check_json_keys; use std::fmt::Debug; @@ -26,8 +27,8 @@ impl FanboxArticleParagraphBoldStyle { } impl CheckUnkown for FanboxArticleParagraphBoldStyle { - fn check_unknown(&self) -> Result<(), crate::fanbox::error::FanboxAPIError> { - check_json_keys!("offset"+, "length"+,); + fn check_unknown(&self) -> Result<(), FanboxAPIError> { + check_json_keys!("offset"+, "length"+, "type",); Ok(()) } } @@ -41,7 +42,7 @@ impl Debug for FanboxArticleParagraphBoldStyle { } } -#[derive(Debug)] +#[derive(proc_macros::CheckUnkown, Debug)] pub enum FanboxArticleParagraphStyle { Bold(FanboxArticleParagraphBoldStyle), Unknown(JsonValue), @@ -92,6 +93,21 @@ impl FanboxArticleParagraphBlock { } } +impl CheckUnkown for FanboxArticleParagraphBlock { + fn check_unknown(&self) -> Result<(), FanboxAPIError> { + check_json_keys!("styles", "text"+, "type",); + match self.styles() { + Some(styles) => { + for style in styles { + style.check_unknown()?; + } + } + None => {} + } + Ok(()) + } +} + impl Debug for FanboxArticleParagraphBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("FanboxArticleParagraphBlock") @@ -101,7 +117,7 @@ impl Debug for FanboxArticleParagraphBlock { } } -#[derive(Debug)] +#[derive(proc_macros::CheckUnkown, Debug)] pub enum FanboxArticleBlock { Paragraph(FanboxArticleParagraphBlock), Unknown(JsonValue),