message: chore: Add validator derivation to buttplug_derive
diff: @@ -106,6 +106,44 @@ fn impl_buttplug_device_message_macro(ast: &syn::DeriveInput) -> TokenStream {
  }
  }
  +#[proc_macro_derive(ButtplugMessageValidator)]
  +pub fn buttplug_message_validator_derive(input: TokenStream) -> TokenStream {
  + // Construct a representation of Rust code as a syntax tree
  + // that we can manipulate
  + let ast = syn::parse(input).unwrap();
  +
  + // Build the trait implementation
  + impl_buttplug_message_validator_macro(&ast)
  +}
  +
  +fn impl_buttplug_message_validator_macro(ast: &syn::DeriveInput) -> TokenStream {
  + let name = &ast.ident;
  +
  + match &ast.data {
  + syn::Data::Enum(e) => {
  + let idents: Vec<_> = e.variants.iter().map(|x| x.ident.clone()).collect();
  + let gen = quote! {
  + impl ButtplugMessageValidator for #name {
  + fn is_valid(&self) -> Result<(), ButtplugMessageError> {
  + match self {
  + #( #name::#idents(msg) => msg.is_valid(), )*
  + }
  + }
  + }
  + };
  + gen.into()
  + },
  + syn::Data::Struct(_) => {
  + let gen = quote! {
  + impl ButtplugMessageValidator for #name {
  + }
  + };
  + gen.into()
  + }
  + _ => panic!("Derivation only works on structs and enums"),
  + }
  +}
  +
  #[proc_macro_derive(TryFromButtplugClientMessage)]
  pub fn try_from_buttplug_client_message_derive(input: TokenStream) -> TokenStream {
  // Construct a representation of Rust code as a syntax tree
  