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"
|
quote = "1.0.33"
|
||||||
syn = { version = "2.0.41", features = ["extra-traits", "full", "parsing"] }
|
syn = { version = "2.0.41", features = ["extra-traits", "full", "parsing"] }
|
||||||
thiserror = "1.0.51"
|
thiserror = "1.0.51"
|
||||||
trixy-types-derive = {path = "./trixy-types-derive"}
|
|
||||||
|
|
|
@ -30,8 +30,6 @@ use std::{
|
||||||
|
|
||||||
use super::errno;
|
use super::errno;
|
||||||
|
|
||||||
pub use trixy_types_derive::Convertible;
|
|
||||||
|
|
||||||
/// Convert a value into a data structure that we can send directly to c.
|
/// Convert a value into a data structure that we can send directly to c.
|
||||||
pub trait Convertible
|
pub trait Convertible
|
||||||
where
|
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