engine/transaction_derive/src/tracker_field.rs

181 lines
5.6 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
use quote::{format_ident, quote, ToTokens};
use syn::Ident;
use crate::attribute_info::*;
use crate::data_type::*;
use crate::transaction_field::*;
pub struct TrackerField<'a> {
pub variable_name: &'a Ident,
pub data_type: &'a DataType,
pub convert_type: Option<&'a proc_macro2::TokenStream>,
pub attribute_infos: &'a Vec<AttributeInfo>,
}
impl<'a> From<&'a TransactionField> for TrackerField<'a> {
fn from(transaction_field: &'a TransactionField) -> Self {
let convert_type = AttributeInfo::find_convert_type(&transaction_field.attribute_infos);
Self {
variable_name: &transaction_field.variable_name,
data_type: &transaction_field.data_type,
convert_type,
attribute_infos: &transaction_field.attribute_infos,
}
}
}
pub struct TrackerDataType<'a> {
pub variable_name: &'a Ident,
pub data_type: &'a DataType,
pub convert_type: &'a Option<&'a proc_macro2::TokenStream>,
pub attribute_infos: &'a Vec<AttributeInfo>,
}
impl<'a> From<&'a TrackerField<'a>> for TrackerDataType<'a> {
fn from(tracker_field: &'a TrackerField) -> Self {
Self {
variable_name: &tracker_field.variable_name,
data_type: &tracker_field.data_type,
convert_type: &tracker_field.convert_type,
attribute_infos: &tracker_field.attribute_infos,
}
}
}
impl<'a> ToTokens for TrackerDataType<'a> {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let variable_name = &self.variable_name;
let track = format_ident!("track_{}", variable_name);
let last_change = format_ident!("{}_last_change", variable_name);
// figure out the type of the variable
let quote = match self.data_type {
DataType::Array(array) => {
let length = &array.length;
match self.convert_type {
Some(convert_type) => {
quote! {
#variable_name: [Option<#convert_type>; #length],
}
}
None => {
let inner = &array.inner_type;
quote! {
#variable_name: [Option<#inner>; #length],
}
}
}
}
DataType::Vector(vector) => match self.convert_type {
Some(convert_type) => {
quote! {
#variable_name: Vec<Option<#convert_type>>,
}
}
None => {
let inner = &vector.inner_type;
quote! {
#variable_name: Vec<Option<#inner>>,
}
}
},
DataType::Other(ts) => match self.convert_type {
Some(convert_type) => {
quote! {
#variable_name: Option<#convert_type>,
}
}
None => {
quote! {
#variable_name: Option<#ts>,
}
}
},
};
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
// set variable type
proc_macro2::TokenStream::from(quote).to_tokens(tokens);
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
// flag, if variable gets tracked
proc_macro2::TokenStream::from(quote! {
#track: bool,
})
.to_tokens(tokens);
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
// track the time the variable got changed last time
proc_macro2::TokenStream::from(match self.data_type {
DataType::Array(array) => {
let length = &array.length;
quote! {#last_change: [std::time::Duration; #length],}
}
DataType::Vector(_) => {
quote! {#last_change: Vec<std::time::Duration>,}
}
DataType::Other(_) => {
quote! {#last_change: std::time::Duration,}
}
})
.to_tokens(tokens);
}
}
pub struct TrackerDefault<'a> {
pub variable_name: &'a Ident,
pub attribute_infos: &'a Vec<AttributeInfo>,
}
impl<'a> From<&'a TrackerDataType<'a>> for TrackerDefault<'a> {
fn from(tracker_field: &'a TrackerDataType) -> Self {
Self {
variable_name: &tracker_field.variable_name,
attribute_infos: &tracker_field.attribute_infos,
}
}
}
impl<'a> ToTokens for TrackerDefault<'a> {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let variable_name = &self.variable_name;
let track = format_ident!("track_{}", variable_name);
let last_change = format_ident!("{}_last_change", variable_name);
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
proc_macro2::TokenStream::from(quote! {
#variable_name: Default::default(),
})
.to_tokens(tokens);
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
proc_macro2::TokenStream::from(quote! {
#track: true,
})
.to_tokens(tokens);
// check features
AttributeInfo::set_features(&self.attribute_infos, tokens);
proc_macro2::TokenStream::from(quote! {
#last_change: Default::default(),
})
.to_tokens(tokens);
}
}