From 918ab5df6d8df43c2e41e2ca6b40d78d92bf24a3 Mon Sep 17 00:00:00 2001 From: Soispha Date: Sun, 24 Mar 2024 18:04:23 +0100 Subject: [PATCH] refactor(macros/convertible_derive): Generate the `Convertible` Trait impl Previously this was derived in the `trixy-types-derive` create, but this is just making debugging harder and has thus been refactored. --- .../src/generate/convertible_derive.rs | 148 ++++++++++++++++++ trixy-types/trixy-types-derive/.gitignore | 6 - trixy-types/trixy-types-derive/Cargo.toml | 33 ---- trixy-types/trixy-types-derive/src/lib.rs | 88 ----------- 4 files changed, 148 insertions(+), 127 deletions(-) create mode 100644 trixy-macros/src/generate/convertible_derive.rs delete mode 100644 trixy-types/trixy-types-derive/.gitignore delete mode 100644 trixy-types/trixy-types-derive/Cargo.toml delete mode 100644 trixy-types/trixy-types-derive/src/lib.rs diff --git a/trixy-macros/src/generate/convertible_derive.rs b/trixy-macros/src/generate/convertible_derive.rs new file mode 100644 index 0000000..77a62ae --- /dev/null +++ b/trixy-macros/src/generate/convertible_derive.rs @@ -0,0 +1,148 @@ +/* +* Copyright (C) 2023 - 2024: +* The Trinitrix Project +* +* This file is part of the Trixy crate for Trinitrix. +* +* Trixy is free software: you can redistribute it and/or modify +* it under the terms of the Lesser GNU General Public License as +* published by the Free Software Foundation, either version 3 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* and the Lesser GNU General Public License along with this program. +* If not, see . +*/ + +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use trixy_parser::command_spec::{Enumeration, Structure}; + +use crate::generate::{c_api::mangle_c_type_identifier, identifier_to_rust}; + +/// This function generates the `Convertible` implementation for a structure +pub fn structure_convertable_derive( + structure: &Structure, + paired_type: &TokenStream, +) -> TokenStream { + let ident = identifier_to_rust(&structure.identifier); + + let into_fields: TokenStream = structure + .contents + .iter() + .map(|con| { + let ident = identifier_to_rust(&con.name); + quote! { + #ident: self.#ident.into(), + } + }) + .collect(); + + quote! { + impl trixy::types::traits::convert_trait::Convertible for #ident { + type Ptr = #paired_type; + + fn into_ptr(self) -> Self::Ptr { + Self::Ptr { + #into_fields + } + } + + fn from_ptr(ptr: Self::Ptr) -> Result { + todo!() + } + } + } +} + +/// This function generates the `TryFrom` trait implementation for a given structure +pub fn structure_into_impl(structure: &Structure, paired_type: &TokenStream) -> TokenStream { + let ident = identifier_to_rust(&structure.identifier); + + let try_into_fields: TokenStream = structure + .contents + .iter() + .map(|con| { + let ident = identifier_to_rust(&con.name); + quote! { + #ident: value.#ident.try_into()?, + } + }) + .collect(); + + quote! { + impl TryFrom<#paired_type> for #ident { + type Error = trixy::types::error::TypeConversionError; + + fn try_from(value: #paired_type) -> Result { + Ok(Self { + #try_into_fields + }) + } + } + } +} + +/// This function generates the `From` trait implementation for a given c enumeration +pub fn c_enumeration_into_impl( + enumeration: &Enumeration, + paired_type: &TokenStream, +) -> TokenStream { + let c_ident = mangle_c_type_identifier(&enumeration.identifier); + let ident = identifier_to_rust(&enumeration.identifier); + + enumeration_into_impl( + enumeration, + &c_ident.into_token_stream(), + &ident, + &paired_type, + ) +} + +/// This function generates the `From` trait implementation for a given rust enumeration +pub fn rust_enumeration_into_impl( + enumeration: &Enumeration, + paired_type: &TokenStream, +) -> TokenStream { + let c_ident = mangle_c_type_identifier(&enumeration.identifier); + let ident = identifier_to_rust(&enumeration.identifier); + + enumeration_into_impl( + enumeration, + &ident, + &c_ident.into_token_stream(), + &paired_type, + ) +} + +fn enumeration_into_impl( + enumeration: &Enumeration, + ident_main: &TokenStream, + ident_client: &TokenStream, + paired_type: &TokenStream, +) -> TokenStream { + let match_lines: TokenStream = enumeration + .states + .iter() + .map(|state| { + let name = identifier_to_rust(&(state.into())); + quote! { + #ident_client :: #name => Self :: #name, + } + }) + .collect(); + quote! { + impl From<#paired_type> for #ident_main { + fn from(value: #paired_type) -> Self { + match value { + #match_lines + } + } + } + } +} diff --git a/trixy-types/trixy-types-derive/.gitignore b/trixy-types/trixy-types-derive/.gitignore deleted file mode 100644 index 20c0ba9..0000000 --- a/trixy-types/trixy-types-derive/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# build -/target -/result - -# This crate is a library -Cargo.lock diff --git a/trixy-types/trixy-types-derive/Cargo.toml b/trixy-types/trixy-types-derive/Cargo.toml deleted file mode 100644 index f8bcaad..0000000 --- a/trixy-types/trixy-types-derive/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2023 - 2024: -# The Trinitrix Project -# -# This file is part of the Trixy crate for Trinitrix. -# -# Trixy is free software: you can redistribute it and/or modify -# it under the terms of the Lesser GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# and the Lesser GNU General Public License along with this program. -# If not, see . - -[package] -name = "trixy-types-derive" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -syn = "1.0" -quote = "1.0" -proc-macro2 = "1.0.78" - -[lib] -proc-macro = true diff --git a/trixy-types/trixy-types-derive/src/lib.rs b/trixy-types/trixy-types-derive/src/lib.rs deleted file mode 100644 index 16afa0a..0000000 --- a/trixy-types/trixy-types-derive/src/lib.rs +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (C) 2023 - 2024: -* The Trinitrix Project -* -* This file is part of the Trixy crate for Trinitrix. -* -* Trixy is free software: you can redistribute it and/or modify -* it under the terms of the Lesser GNU General Public License as -* published by the Free Software Foundation, either version 3 of -* the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* and the Lesser GNU General Public License along with this program. -* If not, see . -*/ - -use proc_macro::TokenStream; -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use syn::{Fields, FieldsNamed}; - -#[proc_macro_derive(Convertible)] -pub fn convertible_derive(input: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(input).unwrap(); - let name = &ast.ident; - - let drop_impl = match ast.data { - syn::Data::Struct(stru) => { - let field_drop = if let Fields::Named(FieldsNamed { - brace_token: _, - named, - }) = stru.fields - { - named - .iter() - .map(|field| field.ident.as_ref().expect("All are under NamedFields")) - .map(|name| { - quote! { - self.#name.drop_ptr()?; - } - }) - .collect::() - } else { - unimplemented!() - }; - - quote! { - impl trixy::types::traits::convert_trait::Convertible for #name { - type Ptr = #name; - - fn into_ptr(self) -> Self::Ptr { - self - } - - fn from_ptr(ptr: Self::Ptr) -> Result { - // #field_drop - // Ok(()) - Err(trixy::types::error::TypeConversionError::NotAdmissable) - } - } - } - } - syn::Data::Enum(_) => { - quote! { - impl trixy::types::traits::convert_trait::Convertible for #name { - type Ptr = #name ; - - fn into_ptr(self) -> Self::Ptr { - self - } - - fn from_ptr(ptr: Self::Ptr) -> Result { - // log::warn!("Drop does nothing on enums! (Called for {})", stringify!(#name)); - Err(trixy::types::error::TypeConversionError::NotAdmissable) - } - } - } - } - syn::Data::Union(_) => panic!("This derive macro does nothing for unions"), - }; - - drop_impl.into() -}