1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#![allow(unused_imports, unused_macros)] extern crate proc_macro; use proc_macro::TokenStream; use quote::{quote, quote_spanned, format_ident, ToTokens}; use syn::{ spanned::Spanned, parse_macro_input, DeriveInput }; mod codegen; mod meta_attrs; mod binread_endian; mod compiler_error; use codegen::sanitization::*; use proc_macro2::{TokenStream as TokenStream2, Span}; use compiler_error::{CompileError, SpanError}; fn generate_derive(input: DeriveInput, code: codegen::GeneratedCode) -> TokenStream { let codegen::GeneratedCode { read_opt_impl, after_parse_impl, arg_type } = code; let name = input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote!( #[allow(warnings)] impl #impl_generics #TRAIT_NAME for #name #ty_generics #where_clause { type Args = #arg_type; fn read_options<R: #READ_TRAIT + #SEEK_TRAIT> (#READER: &mut R, #OPT: &#OPTIONS, #ARGS: Self::Args) -> #BIN_RESULT<Self> { #read_opt_impl } fn after_parse<R: #READ_TRAIT + #SEEK_TRAIT> (&mut self, #READER: &mut R, #OPT : &#OPTIONS, #ARGS : Self::Args) -> #BIN_RESULT<()> { #after_parse_impl } } ).into() } #[proc_macro_derive(BinRead, attributes(binread, br))] pub fn derive_binread(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input as DeriveInput); match codegen::generate(&input) { Ok(code) => { generate_derive(input, code) } Err(err) => { let error = match err { CompileError::SpanError(span_err) => { let SpanError (span, error) = span_err; let error: &str = &error; quote_spanned!{ span => compile_error!(#error) } } CompileError::Syn(syn_err) => syn_err.to_compile_error() }; generate_derive(input, codegen::GeneratedCode::new( quote!(todo!()), error, quote!(()) )) } } }