336 lines
12 KiB
Rust
336 lines
12 KiB
Rust
use quote::{format_ident, quote, ToTokens};
|
|
use syn::Ident;
|
|
|
|
use crate::attribute_info::*;
|
|
use crate::data_type::*;
|
|
|
|
#[derive(Debug)]
|
|
pub struct TransactionField {
|
|
pub variable_name: Ident,
|
|
pub data_type: DataType,
|
|
pub attribute_infos: Vec<AttributeInfo>,
|
|
|
|
pub tracker: Option<Ident>,
|
|
}
|
|
|
|
impl ToTokens for TransactionField {
|
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
|
let setter = format_ident!("set_{}", self.variable_name);
|
|
let updater = format_ident!("update_{}", self.variable_name);
|
|
let var = &self.variable_name;
|
|
let ty = &self.data_type;
|
|
let tracker = self.tracker.as_ref().expect("tracker not set");
|
|
let track = format_ident!("track_{}", var);
|
|
|
|
let pre_exec_function = AttributeInfo::find_pre_setter_exec_function(&self.attribute_infos);
|
|
let exec_function = AttributeInfo::find_setter_exec_function(&self.attribute_infos);
|
|
let convert_type = AttributeInfo::find_convert_type(&self.attribute_infos);
|
|
let custom_from = AttributeInfo::find_custom_from(&self.attribute_infos);
|
|
|
|
let visibility = if AttributeInfo::find_private_setter(&self.attribute_infos) {
|
|
quote! {}
|
|
} else {
|
|
quote! {pub}
|
|
};
|
|
|
|
let setter = match ty {
|
|
DataType::Vector(vector) => {
|
|
let vector_type = &vector.inner_type;
|
|
|
|
match (exec_function, pre_exec_function) {
|
|
(Some(exec_function), Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #vector_type, index: usize) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var[index] != v {
|
|
let old_value = std::mem::replace(&mut self.#var[index], v);
|
|
|
|
self.#exec_function(old_value, index).unwrap();
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(Some(exec_function), None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #vector_type, index: usize) {
|
|
if self.#var[index] != #var {
|
|
let old_value = std::mem::replace(&mut self.#var[index], #var);
|
|
|
|
self.#exec_function(old_value, index).unwrap();
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #vector_type, index: usize) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var[index] != v {
|
|
let old_value = std::mem::replace(&mut self.#var[index], v);
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #vector_type, index: usize) {
|
|
if self.#var[index] != #var {
|
|
self.#var[index] = #var;
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DataType::Array(array) => {
|
|
let array_type = &array.inner_type;
|
|
|
|
match (exec_function, pre_exec_function) {
|
|
(Some(exec_function), Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #array_type, index: usize) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var[index] != v {
|
|
let old_value = std::mem::replace(&mut self.#var[index], v);
|
|
|
|
self.#exec_function(old_value, index).unwrap();
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(Some(exec_function), None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #array_type, index: usize) {
|
|
if self.#var[index] != #var {
|
|
let old_value = std::mem::replace(&mut self.#var[index], #var);
|
|
|
|
self.#exec_function(old_value, index).unwrap();
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #array_type, index: usize) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var[index] != v {
|
|
let old_value = std::mem::replace(&mut self.#var[index], v);
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #array_type, index: usize) {
|
|
if self.#var[index] != #var {
|
|
self.#var[index] = #var;
|
|
|
|
self.#updater(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DataType::Other(ts) => match (exec_function, pre_exec_function) {
|
|
(Some(exec_function), Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #ts) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var != v {
|
|
let old_value = std::mem::replace(&mut self.#var, v);
|
|
|
|
self.#exec_function(old_value).unwrap();
|
|
|
|
self.#updater();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(Some(exec_function), None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #ts) {
|
|
if self.#var != #var {
|
|
let old_value = std::mem::replace(&mut self.#var, #var);
|
|
|
|
self.#exec_function(old_value).unwrap();
|
|
|
|
self.#updater();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, Some(pre_exec_function)) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #ts) {
|
|
let v = self.#pre_exec_function(#var);
|
|
|
|
if self.#var != v {
|
|
let old_value = std::mem::replace(&mut self.#var, v);
|
|
|
|
self.#updater();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(None, None) => {
|
|
quote! {
|
|
fn #setter(&mut self, #var: #ts) {
|
|
if self.#var != #var {
|
|
self.#var = #var;
|
|
|
|
self.#updater();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|
|
// check features
|
|
AttributeInfo::set_features(&self.attribute_infos, tokens);
|
|
|
|
proc_macro2::TokenStream::from(quote! {
|
|
#visibility #setter
|
|
})
|
|
.to_tokens(tokens);
|
|
|
|
if !AttributeInfo::find_skip_getter(&self.attribute_infos) {
|
|
let getter = match ty {
|
|
DataType::Array(array) => {
|
|
let complete_type = &array.full_type;
|
|
|
|
quote! {
|
|
pub fn #var(&self) -> &#complete_type {
|
|
&self.#var
|
|
}
|
|
}
|
|
}
|
|
DataType::Vector(vector) => {
|
|
let complete_type = &vector.full_type;
|
|
|
|
quote! {
|
|
pub fn #var(&self) -> &#complete_type {
|
|
&self.#var
|
|
}
|
|
}
|
|
}
|
|
DataType::Other(ts) => {
|
|
quote! {
|
|
pub fn #var(&self) -> &#ts {
|
|
&self.#var
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// check features
|
|
AttributeInfo::set_features(&self.attribute_infos, tokens);
|
|
|
|
proc_macro2::TokenStream::from(getter).to_tokens(tokens);
|
|
}
|
|
|
|
// check features
|
|
AttributeInfo::set_features(&self.attribute_infos, tokens);
|
|
|
|
proc_macro2::TokenStream::from(quote! {
|
|
pub fn #track(&mut self, track: bool) {
|
|
self.#tracker.#track = track;
|
|
}
|
|
})
|
|
.to_tokens(tokens);
|
|
|
|
// check features
|
|
AttributeInfo::set_features(&self.attribute_infos, tokens);
|
|
|
|
let indexed_type_conversion = match (convert_type, custom_from) {
|
|
(Some(_convert_type), Some(custom_from)) => quote! {
|
|
Some(Self::#custom_from(self.#var[index].clone()))
|
|
},
|
|
(Some(convert_type), None) => quote! {
|
|
Some(#convert_type::from(self.#var[index].clone()))
|
|
},
|
|
(None, _) => quote! {
|
|
Some(self.#var[index].clone())
|
|
},
|
|
};
|
|
|
|
let type_conversion = match (convert_type, custom_from) {
|
|
(Some(_convert_type), Some(custom_from)) => quote! {
|
|
Some(Self::#custom_from(self.#var.clone()))
|
|
},
|
|
(Some(convert_type), None) => quote! {
|
|
Some(#convert_type::from(self.#var.clone()))
|
|
},
|
|
(None, _) => quote! {
|
|
Some(self.#var.clone())
|
|
},
|
|
};
|
|
|
|
let update = match ty {
|
|
DataType::Vector(_vector) => {
|
|
let check_vector_length = quote! {
|
|
if self.#tracker.#var.len() as i32 - 1 < index as i32 {
|
|
let size_difference = index as i32 - (self.#tracker.#var.len() as i32 - 1);
|
|
|
|
for _ in 0..size_difference {
|
|
self.#tracker.#var.push(None);
|
|
}
|
|
}
|
|
};
|
|
|
|
quote! {
|
|
#[inline]
|
|
pub fn #updater(&mut self, index: usize) {
|
|
if self.#tracker.#track {
|
|
#check_vector_length
|
|
|
|
self.#tracker.#var[index] = #indexed_type_conversion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DataType::Array(_array) => {
|
|
quote! {
|
|
#[inline]
|
|
pub fn #updater(&mut self, index: usize) {
|
|
if self.#tracker.#track {
|
|
self.#tracker.#var[index] = #indexed_type_conversion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DataType::Other(_ts) => {
|
|
quote! {
|
|
#[inline]
|
|
pub fn #updater(&mut self) {
|
|
if self.#tracker.#track {
|
|
self.#tracker.#var = #type_conversion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
proc_macro2::TokenStream::from(update).to_tokens(tokens);
|
|
}
|
|
}
|