An unofficial collection of APIs used in FreeJam games and mods
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

50 lignes
1.6KB

  1. //! Macro implementation for using #[derive(Parsable)]
  2. extern crate proc_macro;
  3. use proc_macro::{TokenStream};
  4. use syn::{DeriveInput, Data};
  5. use quote::quote;
  6. /// Macro generator
  7. #[proc_macro_derive(Parsable)]
  8. pub fn derive_parsable(struc: TokenStream) -> TokenStream {
  9. let ast: &DeriveInput = &syn::parse(struc).unwrap();
  10. let name = &ast.ident;
  11. if let Data::Struct(data_struct) = &ast.data {
  12. let mut p_fields_gen = vec![];
  13. let mut d_fields_gen = vec![];
  14. for field in &data_struct.fields {
  15. let field_ident = &field.ident.clone().expect("Expected named field");
  16. let field_type = &field.ty;
  17. p_fields_gen.push(
  18. quote! {
  19. #field_ident: <#field_type>::parse(data)?
  20. }
  21. );
  22. d_fields_gen.push(
  23. quote! {
  24. self.#field_ident.dump(data)?;
  25. }
  26. );
  27. }
  28. let final_gen = quote! {
  29. impl Parsable for #name {
  30. fn parse(data: &mut dyn std::io::Read) -> std::io::Result<Self> {
  31. Ok(Self{
  32. #(#p_fields_gen),*
  33. })
  34. }
  35. fn dump(&self, data: &mut dyn std::io::Write) -> std::io::Result<usize> {
  36. let mut write_count: usize = 0;
  37. #(write_count += #d_fields_gen;)*
  38. Ok(write_count)
  39. }
  40. }
  41. };
  42. return final_gen.into();
  43. } else {
  44. panic!("Expected Parsable auto-trait to be applied to struct");
  45. }
  46. }