From b5f5ae8b035d323525e2c41399e38be933ce6188 Mon Sep 17 00:00:00 2001 From: Soispha Date: Wed, 27 Mar 2024 22:09:08 +0100 Subject: [PATCH] fix(macros/generate/host): Add unified support for conversions These include from the c type to rust, vice versa. --- .../convert/host/c/enumeration/mod.rs | 19 +--------- .../generate/convert/host/c/identifier/mod.rs | 16 +++++++- .../generate/convert/host/c/structure/mod.rs | 5 ++- .../convert/host/rust/derive/enumeration.rs | 4 +- .../convert/host/rust/derive/structure.rs | 37 ++++++++++++++----- .../convert/host/rust/identifier/mod.rs | 18 +++++++++ .../convert/host/rust/structure/mod.rs | 17 ++------- 7 files changed, 71 insertions(+), 45 deletions(-) diff --git a/src/macros/generate/convert/host/c/enumeration/mod.rs b/src/macros/generate/convert/host/c/enumeration/mod.rs index c896a61..56e8c1d 100644 --- a/src/macros/generate/convert/host/c/enumeration/mod.rs +++ b/src/macros/generate/convert/host/c/enumeration/mod.rs @@ -35,24 +35,7 @@ impl Enumeration { .collect(); let states: Vec = self.states.iter().map(DocIdentifier::to_rust).collect(); - let paired_type = { - let path = &self - .identifier - .variant - .to_rust_path() - .expect("This should always be some for enums"); - - let ident = &self.identifier.to_rust(); - if path.is_empty() { - quote! { - crate :: #ident - } - } else { - quote! { - #path :: #ident - } - } - }; + let paired_type = self.identifier.to_rust_paired(); let convertible = &self.derive_from_c_paried_rust(&paired_type); quote! { diff --git a/src/macros/generate/convert/host/c/identifier/mod.rs b/src/macros/generate/convert/host/c/identifier/mod.rs index 36871b4..c8ae4ad 100644 --- a/src/macros/generate/convert/host/c/identifier/mod.rs +++ b/src/macros/generate/convert/host/c/identifier/mod.rs @@ -21,7 +21,7 @@ */ use proc_macro2::TokenStream as TokenStream2; -use quote::{format_ident, ToTokens}; +use quote::{format_ident, quote, ToTokens}; use crate::parser::command_spec::Identifier; @@ -45,4 +45,18 @@ impl Identifier { pub fn to_c(&self) -> TokenStream2 { format_ident!("{}_c", self.name).to_token_stream() } + + pub fn to_c_paired(&self) -> TokenStream2 { + let path = &self.variant.to_c_path(); + let ident = &self.to_c(); + if path.is_empty() { + quote! { + crate :: #ident + } + } else { + quote! { + #path :: #ident + } + } + } } diff --git a/src/macros/generate/convert/host/c/structure/mod.rs b/src/macros/generate/convert/host/c/structure/mod.rs index 7d49e30..c3950f8 100644 --- a/src/macros/generate/convert/host/c/structure/mod.rs +++ b/src/macros/generate/convert/host/c/structure/mod.rs @@ -36,7 +36,9 @@ impl Structure { let contents: Vec = self.contents.iter().map(DocNamedType::to_c).collect(); - // TODO: Convertible <2024-03-08> + let paired_type = self.identifier.to_rust_paired(); + + let into_impl = &self.derive_from_c_paired_rust(&paired_type); quote! { #doc_comments #[allow(non_camel_case_types)] @@ -45,6 +47,7 @@ impl Structure { pub struct #ident { #(#contents),* } + #into_impl } } } diff --git a/src/macros/generate/convert/host/rust/derive/enumeration.rs b/src/macros/generate/convert/host/rust/derive/enumeration.rs index 6f09433..3a0253c 100644 --- a/src/macros/generate/convert/host/rust/derive/enumeration.rs +++ b/src/macros/generate/convert/host/rust/derive/enumeration.rs @@ -29,7 +29,7 @@ impl Enumeration { fn derive_from_paired( &self, ident_self: &TokenStream2, - ident_paired: &TokenStream2, + _ident_paired: &TokenStream2, paired_type: &TokenStream2, ) -> TokenStream2 { let match_lines: TokenStream2 = self @@ -38,7 +38,7 @@ impl Enumeration { .map(|state| { let name = Into::::into(state).to_rust(); quote! { - #ident_paired :: #name => Self :: #name, + #paired_type :: #name => Self :: #name, } }) .collect(); diff --git a/src/macros/generate/convert/host/rust/derive/structure.rs b/src/macros/generate/convert/host/rust/derive/structure.rs index 9224fd7..f7227f2 100644 --- a/src/macros/generate/convert/host/rust/derive/structure.rs +++ b/src/macros/generate/convert/host/rust/derive/structure.rs @@ -60,23 +60,26 @@ impl Structure { } /// This function generates the `TryFrom` trait implementation for a given structure - // was: `structure_into_impl` - pub fn derive_into_impl(&self, paired_type: &TokenStream2) -> TokenStream2 { - let ident = self.identifier.to_rust(); - + /// This function is more low-level, prefer to use the [`derive_from_c_paired_rust`] and + /// [`derive_from_rust_paired_c`] functions instead. + pub fn derive_from_paired( + &self, + ident_self: &TokenStream2, + paired_type: &TokenStream2, + ) -> TokenStream2 { let try_into_fields: TokenStream2 = self .contents .iter() - .map(|con| { - let ident = &con.name.to_rust(); + .map(|content| { + let name = content.name.to_rust(); quote! { - #ident: value.#ident.try_into()?, + // #paired_type :: #name => Self :: #name, + #name: value.#name.try_into()?, } }) .collect(); - quote! { - impl TryFrom<#paired_type> for #ident { + impl TryFrom<#paired_type> for #ident_self { type Error = trixy::types::error::TypeConversionError; fn try_from(value: #paired_type) -> Result { @@ -87,4 +90,20 @@ impl Structure { } } } + + /// This function generates the `TryFrom` trait implementation for a given c + /// structure + pub fn derive_from_c_paired_rust(&self, paired_rust_type: &TokenStream2) -> TokenStream2 { + let c_ident = self.identifier.to_c(); + + self.derive_from_paired(&c_ident, &paired_rust_type) + } + + /// This function generates the `TryFrom` trait implementation for a given rust + /// structure + pub fn derive_from_rust_paired_c(&self, paired_c_type: &TokenStream2) -> TokenStream2 { + let rust_ident = self.identifier.to_rust(); + + self.derive_from_paired(&rust_ident, &paired_c_type) + } } diff --git a/src/macros/generate/convert/host/rust/identifier/mod.rs b/src/macros/generate/convert/host/rust/identifier/mod.rs index 8fc74d1..91fe0ad 100644 --- a/src/macros/generate/convert/host/rust/identifier/mod.rs +++ b/src/macros/generate/convert/host/rust/identifier/mod.rs @@ -48,4 +48,22 @@ impl Identifier { #pascal_ident } } + + pub fn to_rust_paired(&self) -> TokenStream2 { + let path = &self + .variant + .to_rust_path() + .expect("This should be generatable, when this function is called"); + + let ident = &self.to_rust(); + if path.is_empty() { + quote! { + crate :: #ident + } + } else { + quote! { + #path :: #ident + } + } + } } diff --git a/src/macros/generate/convert/host/rust/structure/mod.rs b/src/macros/generate/convert/host/rust/structure/mod.rs index 3749cc4..0c27eaa 100644 --- a/src/macros/generate/convert/host/rust/structure/mod.rs +++ b/src/macros/generate/convert/host/rust/structure/mod.rs @@ -34,22 +34,11 @@ impl Structure { .collect(); let ident = &self.identifier.to_rust(); - let c_ident = { - let path = &self.identifier.variant.to_c_path(); - let ident = &self.identifier.to_c(); - if path.is_empty() { - quote! { - crate :: #ident - } - } else { - quote! { - #path :: #ident - } - } - }; let contents: Vec = self.contents.iter().map(DocNamedType::to_rust).collect(); + + let c_ident = self.identifier.to_c_paired(); let convertible = self.derive_convertible(&c_ident); - let into_impl = self.derive_into_impl(&c_ident); + let into_impl = self.derive_from_rust_paired_c(&c_ident); quote! { #doc_comments