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.
This commit is contained in:
parent
938e038075
commit
18034e28de
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Self, trixy::types::error::TypeConversionError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function generates the `TryFrom<paired_type>` 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<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
#try_into_fields
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function generates the `From<paired_type>` 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<paired_type>` 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,4 +30,3 @@ proc-macro2 = "1.0.70"
|
|||
quote = "1.0.33"
|
||||
syn = { version = "2.0.41", features = ["extra-traits", "full", "parsing"] }
|
||||
thiserror = "1.0.51"
|
||||
trixy-types-derive = {path = "./trixy-types-derive"}
|
||||
|
|
|
@ -30,8 +30,6 @@ use std::{
|
|||
|
||||
use super::errno;
|
||||
|
||||
pub use trixy_types_derive::Convertible;
|
||||
|
||||
/// Convert a value into a data structure that we can send directly to c.
|
||||
pub trait Convertible
|
||||
where
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# build
|
||||
/target
|
||||
/result
|
||||
|
||||
# This crate is a library
|
||||
Cargo.lock
|
|
@ -1,33 +0,0 @@
|
|||
# Copyright (C) 2023 - 2024:
|
||||
# The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
#
|
||||
# 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
[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
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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::<TokenStream2>()
|
||||
} 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<Self, trixy::types::error::TypeConversionError> {
|
||||
// #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<Self, trixy::types::error::TypeConversionError> {
|
||||
// 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()
|
||||
}
|
Reference in New Issue