fixcol_derive/
lib.rs

1//! A proc macro crate for deriving [`ReadFixed`] and [`WriteFixed`]
2//!
3//! This crate, `fixcol-derive` contains the proc-macro derive functionality for
4//! the [`fixcol`](https://docs.rs/fixcol/latest/fixcol/) crate. Unless you are
5//! planning on contributing to `fixcol`, you probably want one of the following.
6//!
7//!  - [Crate](https://crates.io/crates/fixcol)
8//!  - [Documentation](https://docs.rs/fixcol/latest/fixcol)
9//!  - [Repository](https://github.com/BrianLondon/fixcol)
10//!
11//! [`ReadFixed`]: https://docs.rs/fixcol/latest/fixcol/trait.ReadFixed.html
12//! [`WriteFixed`]: https://docs.rs/fixcol/latest/fixcol/trait.WriteFixed.html
13mod attrs;
14mod enums;
15mod error;
16mod fields;
17mod structs;
18
19extern crate proc_macro;
20extern crate proc_macro2;
21extern crate quote;
22extern crate syn;
23
24use enums::enum_write;
25use error::MacroError;
26use proc_macro::TokenStream;
27use quote::quote;
28use syn::spanned::Spanned;
29use syn::{Data, DataEnum, DataStruct, DeriveInput};
30
31use crate::enums::enum_read;
32use crate::structs::{struct_read, struct_write};
33
34/// Derive proc-macro for ReadFixed
35///
36/// See documentation on [`ReadFixed`] for a full description.
37///
38/// [`ReadFixed`]: https://docs.rs/fixcol/latest/fixcol/trait.ReadFixed.html
39#[proc_macro_derive(ReadFixed, attributes(fixcol))]
40pub fn read_fixed_impl(input: TokenStream) -> TokenStream {
41    let ast: DeriveInput = syn::parse(input).unwrap();
42
43    let name = &ast.ident;
44    let attrs = &ast.attrs;
45    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
46
47    let function_impl_result = match ast.data {
48        Data::Struct(DataStruct { fields, .. }) => struct_read(name, attrs, fields),
49        Data::Enum(DataEnum { variants, .. }) => enum_read(name, attrs, variants.iter().collect()),
50        Data::Union(u) => Err(MacroError::new(
51            "Deriving ReadFixed on unions is not supported",
52            u.union_token.span(),
53        )),
54    };
55
56    let gen = match function_impl_result {
57        Ok(function_impl) => {
58            quote! {
59                impl #impl_generics fixcol::ReadFixed for #name #ty_generics #where_clause {
60                    #function_impl
61                }
62            }
63        }
64        Err(err) => quote! { #err },
65    };
66
67    // println!("{}", gen);
68
69    gen.into()
70}
71
72/// Derive proc-macro for WriteFixed
73///
74/// See [`WriteFixed`] for a complete discuassion.
75///
76/// [`WriteFixed`]: https://docs.rs/fixcol/latest/fixcol/trait.WriteFixed.html
77#[proc_macro_derive(WriteFixed, attributes(fixcol))]
78pub fn write_fixed_impl(input: TokenStream) -> TokenStream {
79    let ast: DeriveInput = syn::parse(input).unwrap();
80
81    let name = &ast.ident;
82    let attrs = &ast.attrs;
83    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
84
85    let function_impl_result = match ast.data {
86        Data::Struct(DataStruct { fields, .. }) => struct_write(name, attrs, fields),
87        Data::Enum(DataEnum { variants, .. }) => {
88            enum_write(name, attrs, &variants.iter().collect::<Vec<_>>())
89        }
90        Data::Union(u) => Err(MacroError::new(
91            "Deriving WriteFixed on unions is not supported",
92            u.union_token.span(),
93        )),
94    };
95
96    let gen = match function_impl_result {
97        Ok(function_impl) => {
98            quote! {
99                impl #impl_generics fixcol::WriteFixed for #name #ty_generics #where_clause {
100                    #function_impl
101                }
102            }
103        }
104        Err(err) => quote! { #err },
105    };
106
107    // println!("{}", gen);
108
109    gen.into()
110}
111
112#[cfg(test)]
113mod tests {
114    // use super::*;
115
116    #[test]
117    fn macro_test() {
118        assert!(true);
119    }
120}