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
78
79
80
81
82
83
84
85
86
87
88
89
90
#![warn(clippy::pedantic)]
#![warn(rust_2018_idioms)]
#![cfg_attr(nightly, feature(proc_macro_span))]
#![cfg_attr(coverage_nightly, feature(coverage_attribute))]

extern crate alloc;

mod binrw;
mod fn_helper;
mod meta_types;
mod named_args;
mod result;
pub(crate) mod util;

use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_attribute]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn binread(attr: TokenStream, input: TokenStream) -> TokenStream {
    binrw::derive_from_attribute(&attr, input, false)
}

#[proc_macro_derive(BinRead, attributes(br, brw))]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn binread_derive(input: TokenStream) -> TokenStream {
    binrw::derive_from_input(
        parse_macro_input!(input as DeriveInput),
        binrw::Options {
            derive: true,
            write: false,
        },
    )
    .into()
}

#[proc_macro_attribute]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn binrw(attr: TokenStream, input: TokenStream) -> TokenStream {
    if attr.to_string() == "ignore" {
        input
    } else {
        binrw::binrw_derive(parse_macro_input!(input as DeriveInput)).into()
    }
}

#[proc_macro_derive(BinWrite, attributes(bw, brw))]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn binwrite_derive(input: TokenStream) -> TokenStream {
    binrw::derive_from_input(
        parse_macro_input!(input as DeriveInput),
        binrw::Options {
            derive: true,
            write: true,
        },
    )
    .into()
}

#[proc_macro_attribute]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn binwrite(attr: TokenStream, input: TokenStream) -> TokenStream {
    binrw::derive_from_attribute(&attr, input, true)
}

#[proc_macro_derive(NamedArgs, attributes(named_args))]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn named_args_derive(input: TokenStream) -> TokenStream {
    named_args::derive_from_input(parse_macro_input!(input as DeriveInput)).into()
}

#[proc_macro_attribute]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn parser(attr: TokenStream, input: TokenStream) -> TokenStream {
    fn_helper::derive_from_attribute::<false>(attr, input)
}

#[proc_macro_attribute]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn writer(attr: TokenStream, input: TokenStream) -> TokenStream {
    fn_helper::derive_from_attribute::<true>(attr, input)
}

fn combine_error(all_errors: &mut Option<syn::Error>, new_error: syn::Error) {
    if let Some(all_errors) = all_errors {
        all_errors.combine(new_error);
    } else {
        *all_errors = Some(new_error);
    }
}