fix(macros/generate/host): Add unified support for conversions

These include from the c type to rust, vice versa.
This commit is contained in:
Benedikt Peetz 2024-03-27 22:09:08 +01:00
parent 3d35d395f3
commit b5f5ae8b03
Signed by: bpeetz
GPG Key ID: A5E94010C3A642AD
7 changed files with 71 additions and 45 deletions

View File

@ -35,24 +35,7 @@ impl Enumeration {
.collect(); .collect();
let states: Vec<TokenStream2> = self.states.iter().map(DocIdentifier::to_rust).collect(); let states: Vec<TokenStream2> = self.states.iter().map(DocIdentifier::to_rust).collect();
let paired_type = { let paired_type = self.identifier.to_rust_paired();
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 convertible = &self.derive_from_c_paried_rust(&paired_type); let convertible = &self.derive_from_c_paried_rust(&paired_type);
quote! { quote! {

View File

@ -21,7 +21,7 @@
*/ */
use proc_macro2::TokenStream as TokenStream2; use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, ToTokens}; use quote::{format_ident, quote, ToTokens};
use crate::parser::command_spec::Identifier; use crate::parser::command_spec::Identifier;
@ -45,4 +45,18 @@ impl Identifier {
pub fn to_c(&self) -> TokenStream2 { pub fn to_c(&self) -> TokenStream2 {
format_ident!("{}_c", self.name).to_token_stream() 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
}
}
}
} }

View File

@ -36,7 +36,9 @@ impl Structure {
let contents: Vec<TokenStream2> = self.contents.iter().map(DocNamedType::to_c).collect(); let contents: Vec<TokenStream2> = 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! { quote! {
#doc_comments #doc_comments
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -45,6 +47,7 @@ impl Structure {
pub struct #ident { pub struct #ident {
#(#contents),* #(#contents),*
} }
#into_impl
} }
} }
} }

View File

@ -29,7 +29,7 @@ impl Enumeration {
fn derive_from_paired( fn derive_from_paired(
&self, &self,
ident_self: &TokenStream2, ident_self: &TokenStream2,
ident_paired: &TokenStream2, _ident_paired: &TokenStream2,
paired_type: &TokenStream2, paired_type: &TokenStream2,
) -> TokenStream2 { ) -> TokenStream2 {
let match_lines: TokenStream2 = self let match_lines: TokenStream2 = self
@ -38,7 +38,7 @@ impl Enumeration {
.map(|state| { .map(|state| {
let name = Into::<Identifier>::into(state).to_rust(); let name = Into::<Identifier>::into(state).to_rust();
quote! { quote! {
#ident_paired :: #name => Self :: #name, #paired_type :: #name => Self :: #name,
} }
}) })
.collect(); .collect();

View File

@ -60,23 +60,26 @@ impl Structure {
} }
/// This function generates the `TryFrom<paired_type>` trait implementation for a given structure /// This function generates the `TryFrom<paired_type>` trait implementation for a given structure
// was: `structure_into_impl` /// This function is more low-level, prefer to use the [`derive_from_c_paired_rust`] and
pub fn derive_into_impl(&self, paired_type: &TokenStream2) -> TokenStream2 { /// [`derive_from_rust_paired_c`] functions instead.
let ident = self.identifier.to_rust(); pub fn derive_from_paired(
&self,
ident_self: &TokenStream2,
paired_type: &TokenStream2,
) -> TokenStream2 {
let try_into_fields: TokenStream2 = self let try_into_fields: TokenStream2 = self
.contents .contents
.iter() .iter()
.map(|con| { .map(|content| {
let ident = &con.name.to_rust(); let name = content.name.to_rust();
quote! { quote! {
#ident: value.#ident.try_into()?, // #paired_type :: #name => Self :: #name,
#name: value.#name.try_into()?,
} }
}) })
.collect(); .collect();
quote! { quote! {
impl TryFrom<#paired_type> for #ident { impl TryFrom<#paired_type> for #ident_self {
type Error = trixy::types::error::TypeConversionError; type Error = trixy::types::error::TypeConversionError;
fn try_from(value: #paired_type) -> Result<Self, Self::Error> { fn try_from(value: #paired_type) -> Result<Self, Self::Error> {
@ -87,4 +90,20 @@ impl Structure {
} }
} }
} }
/// This function generates the `TryFrom<paired_type>` 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<paired_type>` 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)
}
} }

View File

@ -48,4 +48,22 @@ impl Identifier {
#pascal_ident #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
}
}
}
} }

View File

@ -34,22 +34,11 @@ impl Structure {
.collect(); .collect();
let ident = &self.identifier.to_rust(); 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<TokenStream2> = self.contents.iter().map(DocNamedType::to_rust).collect(); let contents: Vec<TokenStream2> = self.contents.iter().map(DocNamedType::to_rust).collect();
let c_ident = self.identifier.to_c_paired();
let convertible = self.derive_convertible(&c_ident); 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! { quote! {
#doc_comments #doc_comments