Initial work on FFI
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-09-18 18:02:13 +02:00
parent 39497891e9
commit 726e294f11
19 changed files with 814 additions and 26 deletions

100
src/ffi/mod.rs Normal file
View File

@@ -0,0 +1,100 @@
mod static_data;
type OwnedPtr<T> = *mut T;
type BorrowedPtr<T> = *const T;
macro_rules! ffi_getter {
(
$type:ty, $func:ident, $returns: ty
) => {
paste::paste! {
#[no_mangle]
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<$type>) -> $returns {
ptr.as_ref().$func()
}
}
};
}
macro_rules! ffi_stringkey_getter {
(
$type:ty, $func:ident
) => {
paste::paste! {
#[no_mangle]
extern "C" fn [< $type:lower _ $func >](ptr: ExternPointer<$type>) -> OwnedPtr<c_char> {
std::ffi::CString::new(ptr.as_ref().$func().str()).unwrap().into_raw()
}
}
};
}
macro_rules! ffi_vec_value_getters {
(
$type:ty, $func:ident, $returns: ty
) => {
paste::paste! {
#[no_mangle]
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<$type>) -> usize {
ptr.as_ref().$func().len()
}
#[no_mangle]
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<$type>, index: usize) -> $returns {
*ptr.as_ref().$func().get(index).unwrap()
}
}
};
}
macro_rules! ffi_vec_stringkey_getters {
(
$type:ident, $func:ident
) => {
paste::paste! {
#[no_mangle]
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<$type>) -> usize {
ptr.as_ref().$func().len()
}
#[no_mangle]
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<$type>, index: usize) -> OwnedPtr<c_char> {
CString::new(ptr.as_ref().$func().get(index).unwrap().str()).unwrap().into_raw()
}
}
};
}
pub(self) use ffi_getter;
pub(self) use ffi_stringkey_getter;
pub(self) use ffi_vec_stringkey_getters;
pub(self) use ffi_vec_value_getters;
#[repr(C)]
pub(self) struct ExternPointer<T: ?Sized> {
ptr: *mut T,
}
impl<T: ?Sized> ExternPointer<T> {
pub(self) fn as_ref(&self) -> &T {
unsafe {
self.ptr.as_ref().expect(&format!(
"Given pointer of type '{}' was null",
std::any::type_name::<T>()
))
}
}
pub(self) fn as_mut(&self) -> &mut T {
unsafe {
self.ptr.as_mut().expect(&format!(
"Given pointer of type '{}' was null",
std::any::type_name::<T>()
))
}
}
}
impl<T> Into<ExternPointer<T>> for *mut T {
fn into(self) -> ExternPointer<T> {
ExternPointer { ptr: self }
}
}

View File

@@ -0,0 +1,53 @@
use crate::ffi::{BorrowedPtr, ExternPointer, OwnedPtr};
use crate::static_data::{Ability, EffectParameter};
use crate::StringKey;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
#[no_mangle]
unsafe extern "C" fn ability_new(
name: *const c_char,
effect: *const c_char,
parameters: *const OwnedPtr<EffectParameter>,
parameters_length: usize,
) -> OwnedPtr<Ability> {
let parameters = std::slice::from_raw_parts(parameters, parameters_length);
let mut parameters_vec: Vec<EffectParameter> = Vec::with_capacity(parameters_length);
for parameter in parameters {
parameters_vec.push(*Box::from_raw(*parameter));
}
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
let effect: StringKey = CStr::from_ptr(effect).to_str().unwrap().into();
Box::into_raw(Box::new(Ability::new(&name, &effect, parameters_vec)))
}
#[no_mangle]
unsafe extern "C" fn ability_drop(ptr: OwnedPtr<Ability>) {
drop_in_place(ptr)
}
#[no_mangle]
unsafe extern "C" fn ability_name(ptr: ExternPointer<Ability>) -> OwnedPtr<c_char> {
CString::new(ptr.as_ref().name().str()).unwrap().into_raw()
}
#[no_mangle]
unsafe extern "C" fn ability_effect(ptr: ExternPointer<Ability>) -> OwnedPtr<c_char> {
CString::new(ptr.as_ref().effect().str()).unwrap().into_raw()
}
#[no_mangle]
unsafe extern "C" fn ability_parameter_length(ptr: ExternPointer<Ability>) -> usize {
ptr.as_ref().parameters().len()
}
#[no_mangle]
unsafe extern "C" fn ability_parameter_get(ptr: ExternPointer<Ability>, index: usize) -> BorrowedPtr<EffectParameter> {
if let Some(p) = ptr.as_ref().parameters().get(index) {
p as *const EffectParameter
} else {
std::ptr::null()
}
}

View File

@@ -0,0 +1,90 @@
use crate::ffi::{ffi_getter, ffi_vec_stringkey_getters, ffi_vec_value_getters, BorrowedPtr, ExternPointer, OwnedPtr};
use crate::static_data::{Form, LearnableMoves, StaticStatisticSet, TypeIdentifier};
use crate::StringKey;
use hashbrown::HashSet;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
#[no_mangle]
unsafe extern "C" fn form_new(
name: *const c_char,
height: f32,
weight: f32,
base_experience: u32,
types: *const TypeIdentifier,
types_length: usize,
base_stats: OwnedPtr<StaticStatisticSet<u16>>,
abilities: *const BorrowedPtr<c_char>,
abilities_length: usize,
hidden_abilities: *const BorrowedPtr<c_char>,
hidden_abilities_length: usize,
moves: OwnedPtr<LearnableMoves>,
flags: *const *const c_char,
flags_length: usize,
) -> OwnedPtr<Form> {
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
let abilities = std::slice::from_raw_parts(abilities, abilities_length);
let mut abilities_vec = Vec::with_capacity(abilities_length);
for ability in abilities {
abilities_vec.push(CStr::from_ptr(*ability).into())
}
let hidden_abilities = std::slice::from_raw_parts(hidden_abilities, hidden_abilities_length);
let mut hidden_abilities_vec = Vec::with_capacity(hidden_abilities_length);
for ability in hidden_abilities {
hidden_abilities_vec.push(CStr::from_ptr(*ability).into())
}
let flags = std::slice::from_raw_parts(flags, flags_length);
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
for flag in flags {
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
}
Box::into_raw(Box::new(Form::new(
&name,
height,
weight,
base_experience,
std::slice::from_raw_parts(types, types_length).to_vec(),
*Box::from_raw(base_stats),
abilities_vec,
hidden_abilities_vec,
*Box::from_raw(moves),
flags_set,
)))
}
#[no_mangle]
unsafe extern "C" fn form_drop(ptr: OwnedPtr<Form>) {
drop_in_place(ptr)
}
#[no_mangle]
unsafe extern "C" fn form_name(ptr: ExternPointer<Form>) -> OwnedPtr<c_char> {
let name = ptr.as_ref().name();
CString::new(name.str()).unwrap().into_raw()
}
ffi_getter!(Form, height, f32);
ffi_getter!(Form, weight, f32);
ffi_getter!(Form, base_experience, u32);
ffi_vec_value_getters!(Form, types, TypeIdentifier);
ffi_getter!(Form, base_stats, BorrowedPtr<StaticStatisticSet<u16>>);
ffi_vec_stringkey_getters!(Form, abilities);
ffi_vec_stringkey_getters!(Form, hidden_abilities);
ffi_getter!(Form, moves, BorrowedPtr<LearnableMoves>);
#[no_mangle]
unsafe extern "C" fn form_has_flag(ptr: ExternPointer<Form>, flag: *const c_char) -> u8 {
let flag = CStr::from_ptr(flag).into();
if ptr.as_ref().has_flag(&flag) {
1
} else {
0
}
}

View File

@@ -0,0 +1,27 @@
use crate::defines::LevelInt;
use crate::ffi::{ExternPointer, OwnedPtr};
use crate::static_data::{GrowthRate, LookupGrowthRate};
use std::ptr::drop_in_place;
#[no_mangle]
unsafe extern "C" fn growth_rate_lookup_new(array: *const u32, length: usize) -> OwnedPtr<LookupGrowthRate> {
let array = std::slice::from_raw_parts(array, length);
Box::into_raw(Box::new(LookupGrowthRate::new(array.to_vec())))
}
#[no_mangle]
unsafe extern "C" fn growth_rate_lookup_drop(ptr: OwnedPtr<LookupGrowthRate>) {
drop_in_place(ptr)
}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
extern "C" fn growth_rate_calculate_level(ptr: ExternPointer<dyn GrowthRate>, experience: u32) -> LevelInt {
ptr.as_ref().calculate_level(experience)
}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
extern "C" fn growth_rate_calculate_experience(ptr: ExternPointer<dyn GrowthRate>, level: LevelInt) -> u32 {
ptr.as_ref().calculate_experience(level)
}

View File

@@ -0,0 +1,49 @@
use crate::ffi::{ffi_getter, ExternPointer, OwnedPtr};
use crate::static_data::{BattleItemCategory, Item, ItemCategory};
use crate::StringKey;
use hashbrown::HashSet;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
#[no_mangle]
unsafe extern "C" fn item_new(
name: *const c_char,
category: ItemCategory,
battle_category: BattleItemCategory,
price: i32,
flags: *const *const c_char,
flags_length: usize,
) -> OwnedPtr<Item> {
let flags = std::slice::from_raw_parts(flags, flags_length);
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
for flag in flags {
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
}
Box::into_raw(Box::new(Item::new(&name, category, battle_category, price, flags_set)))
}
#[no_mangle]
unsafe extern "C" fn item_drop(ptr: OwnedPtr<Item>) {
drop_in_place(ptr)
}
#[no_mangle]
unsafe extern "C" fn item_name(ptr: ExternPointer<Item>) -> OwnedPtr<c_char> {
let name = ptr.as_ref().name();
CString::new(name.str()).unwrap().into_raw()
}
ffi_getter!(Item, category, ItemCategory);
ffi_getter!(Item, battle_category, BattleItemCategory);
ffi_getter!(Item, price, i32);
#[no_mangle]
unsafe extern "C" fn item_has_flag(ptr: ExternPointer<Item>, flag: *const c_char) -> u8 {
let flag = CStr::from_ptr(flag).into();
if ptr.as_ref().has_flag(&flag) {
1
} else {
0
}
}

View File

@@ -0,0 +1,24 @@
use crate::defines::LevelInt;
use crate::ffi::{BorrowedPtr, ExternPointer, OwnedPtr};
use crate::static_data::LearnableMoves;
use std::ffi::{c_char, CStr};
use std::ptr::drop_in_place;
#[no_mangle]
extern "C" fn learnable_moves_new() -> OwnedPtr<LearnableMoves> {
Box::into_raw(Box::new(LearnableMoves::new()))
}
#[no_mangle]
unsafe extern "C" fn learnable_moves_drop(ptr: OwnedPtr<LearnableMoves>) {
drop_in_place(ptr)
}
#[no_mangle]
unsafe extern "C" fn learnable_moves_add_level_move(
ptr: ExternPointer<LearnableMoves>,
level: LevelInt,
move_name: BorrowedPtr<c_char>,
) {
ptr.as_mut().add_level_move(level, &CStr::from_ptr(move_name).into())
}

View File

@@ -0,0 +1,87 @@
use crate::ffi::{ExternPointer, OwnedPtr};
use crate::static_data::EffectParameter;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
mod ability;
mod form;
mod growth_rate;
mod item;
mod learnable_moves;
mod move_data;
mod nature;
mod species;
mod statistic_set;
#[no_mangle]
extern "C" fn effect_parameter_new_bool(value: u8) -> OwnedPtr<EffectParameter> {
Box::into_raw(Box::new(EffectParameter::Bool(value == 1)))
}
#[no_mangle]
extern "C" fn effect_parameter_new_int(value: i64) -> OwnedPtr<EffectParameter> {
Box::into_raw(Box::new(EffectParameter::Int(value)))
}
#[no_mangle]
extern "C" fn effect_parameter_new_float(value: f32) -> OwnedPtr<EffectParameter> {
Box::into_raw(Box::new(EffectParameter::Float(value)))
}
#[no_mangle]
unsafe extern "C" fn effect_parameter_new_string(value: *const c_char) -> OwnedPtr<EffectParameter> {
Box::into_raw(Box::new(EffectParameter::String(
CStr::from_ptr(value).to_str().unwrap().into(),
)))
}
#[no_mangle]
unsafe extern "C" fn effect_parameter_drop(ptr: OwnedPtr<EffectParameter>) {
drop_in_place(ptr)
}
#[no_mangle]
extern "C" fn effect_parameter_get_type(ptr: ExternPointer<EffectParameter>) -> u8 {
match ptr.as_ref() {
EffectParameter::Bool(_) => 0,
EffectParameter::Int(_) => 1,
EffectParameter::Float(_) => 2,
EffectParameter::String(_) => 3,
}
}
#[no_mangle]
extern "C" fn effect_parameter_get_as_bool(ptr: ExternPointer<EffectParameter>) -> u8 {
let p = ptr.as_ref();
if let EffectParameter::Bool(b) = p {
return if *b { 1 } else { 0 };
}
panic!("Unexpected effect parameter. Expected bool, was: {}", p);
}
#[no_mangle]
extern "C" fn effect_parameter_get_as_int(ptr: ExternPointer<EffectParameter>) -> i64 {
let p = ptr.as_ref();
if let EffectParameter::Int(b) = p {
return *b;
}
panic!("Unexpected effect parameter. Expected int, was: {}", p);
}
#[no_mangle]
extern "C" fn effect_parameter_get_as_float(ptr: ExternPointer<EffectParameter>) -> f32 {
let p = ptr.as_ref();
if let EffectParameter::Float(b) = p {
return *b;
}
panic!("Unexpected effect parameter. Expected float, was: {}", p);
}
#[no_mangle]
extern "C" fn effect_parameter_get_as_string(ptr: ExternPointer<EffectParameter>) -> OwnedPtr<c_char> {
let p = ptr.as_ref();
if let EffectParameter::String(b) = p {
return CString::new(b.str().to_string()).unwrap().into_raw();
}
panic!("Unexpected effect parameter. Expected string, was: {}", p);
}

View File

@@ -0,0 +1,133 @@
use crate::ffi::{ffi_getter, BorrowedPtr, ExternPointer, OwnedPtr};
use crate::static_data::{EffectParameter, MoveCategory, MoveData, MoveTarget, SecondaryEffect, TypeIdentifier};
use crate::StringKey;
use hashbrown::HashSet;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
#[no_mangle]
unsafe extern "C" fn move_data_new(
name: *const c_char,
move_type: TypeIdentifier,
category: MoveCategory,
base_power: u8,
accuracy: u8,
base_usages: u8,
target: MoveTarget,
priority: i8,
secondary_effect: *mut SecondaryEffect,
flags: *const *const c_char,
flags_length: usize,
) -> OwnedPtr<MoveData> {
let flags = std::slice::from_raw_parts(flags, flags_length);
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
for flag in flags {
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
}
let secondary_effect = if secondary_effect.is_null() {
None
} else {
Some(*Box::from_raw(secondary_effect))
};
Box::into_raw(Box::new(MoveData::new(
&name,
move_type,
category,
base_power,
accuracy,
base_usages,
target,
priority,
secondary_effect,
flags_set,
)))
}
#[no_mangle]
unsafe extern "C" fn move_data_drop(ptr: OwnedPtr<MoveData>) {
drop_in_place(ptr)
}
#[no_mangle]
unsafe extern "C" fn move_data_name(ptr: ExternPointer<MoveData>) -> OwnedPtr<c_char> {
let name = ptr.as_ref().name();
CString::new(name.str()).unwrap().into_raw()
}
ffi_getter!(MoveData, move_type, TypeIdentifier);
ffi_getter!(MoveData, category, MoveCategory);
ffi_getter!(MoveData, base_power, u8);
ffi_getter!(MoveData, accuracy, u8);
ffi_getter!(MoveData, base_usages, u8);
ffi_getter!(MoveData, target, MoveTarget);
ffi_getter!(MoveData, priority, i8);
#[no_mangle]
unsafe extern "C" fn move_data_secondary_effect(ptr: ExternPointer<MoveData>) -> BorrowedPtr<SecondaryEffect> {
let effect = ptr.as_ref().secondary_effect();
if let Some(v) = effect {
v as *const SecondaryEffect
} else {
std::ptr::null()
}
}
#[no_mangle]
unsafe extern "C" fn move_data_has_flag(ptr: ExternPointer<MoveData>, flag: *const c_char) -> u8 {
let flag = CStr::from_ptr(flag).into();
if ptr.as_ref().has_flag(&flag) {
1
} else {
0
}
}
#[no_mangle]
unsafe extern "C" fn secondary_effect_new(
chance: f32,
effect_name: BorrowedPtr<c_char>,
parameters: *mut OwnedPtr<EffectParameter>,
parameters_length: usize,
) -> OwnedPtr<SecondaryEffect> {
let parameter_slice = std::slice::from_raw_parts(parameters, parameters_length);
let mut parameters = Vec::with_capacity(parameters_length);
for parameter in parameter_slice {
parameters.push(*Box::from_raw(*parameter))
}
Box::into_raw(Box::new(SecondaryEffect::new(
chance,
CStr::from_ptr(effect_name).into(),
parameters,
)))
}
#[no_mangle]
unsafe extern "C" fn secondary_effect_drop(ptr: OwnedPtr<SecondaryEffect>) {
drop_in_place(ptr)
}
ffi_getter!(SecondaryEffect, chance, f32);
#[no_mangle]
unsafe extern "C" fn secondary_effect_effect_name(ptr: ExternPointer<SecondaryEffect>) -> OwnedPtr<c_char> {
CString::new(ptr.as_ref().effect_name().str()).unwrap().into_raw()
}
#[no_mangle]
unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer<SecondaryEffect>) -> usize {
ptr.as_ref().parameters().len()
}
#[no_mangle]
unsafe extern "C" fn secondary_effect_parameter_get(
ptr: ExternPointer<SecondaryEffect>,
index: usize,
) -> BorrowedPtr<EffectParameter> {
if let Some(v) = ptr.as_ref().parameters().get(index) {
v as *const EffectParameter
} else {
std::ptr::null()
}
}

View File

@@ -0,0 +1,31 @@
use crate::ffi::{ffi_getter, ExternPointer, OwnedPtr};
use crate::static_data::{Nature, Statistic};
use std::ptr::drop_in_place;
#[no_mangle]
extern "C" fn nature_new(
increase_stat: Statistic,
decrease_stat: Statistic,
increase_modifier: f32,
decrease_modifier: f32,
) -> OwnedPtr<Nature> {
Box::into_raw(Box::new(Nature::new(
increase_stat,
decrease_stat,
increase_modifier,
decrease_modifier,
)))
}
#[no_mangle]
unsafe extern "C" fn nature_drop(ptr: OwnedPtr<Nature>) {
drop_in_place(ptr)
}
ffi_getter!(Nature, increased_stat, Statistic);
ffi_getter!(Nature, decreased_stat, Statistic);
#[no_mangle]
extern "C" fn nature_get_stat_modifier(ptr: ExternPointer<Nature>, stat: Statistic) -> f32 {
ptr.as_ref().get_stat_modifier(stat)
}

View File

@@ -0,0 +1,62 @@
use crate::ffi::{ffi_getter, ffi_stringkey_getter, BorrowedPtr, ExternPointer, OwnedPtr};
use crate::static_data::{Form, Species};
use crate::StringKey;
use hashbrown::HashSet;
use std::ffi::{c_char, CStr};
use std::sync::Arc;
#[no_mangle]
unsafe extern "C" fn species_new(
id: u16,
name: BorrowedPtr<c_char>,
gender_rate: f32,
growth_rate: BorrowedPtr<c_char>,
capture_rate: u8,
default_form: OwnedPtr<Form>,
flags: *const *const c_char,
flags_length: usize,
) -> OwnedPtr<Species> {
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
let growth_rate: StringKey = CStr::from_ptr(growth_rate).to_str().unwrap().into();
let flags = std::slice::from_raw_parts(flags, flags_length);
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
for flag in flags {
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
}
Box::into_raw(Box::new(Species::new(
id,
&name,
gender_rate,
&growth_rate,
capture_rate,
*Box::from_raw(default_form),
flags_set,
)))
}
ffi_getter!(Species, id, u16);
ffi_stringkey_getter!(Species, name);
ffi_getter!(Species, gender_rate, f32);
ffi_stringkey_getter!(Species, growth_rate);
ffi_getter!(Species, capture_rate, u8);
#[no_mangle]
unsafe extern "C" fn species_add_form(
species: ExternPointer<Species>,
name: BorrowedPtr<c_char>,
form: OwnedPtr<Form>,
) {
let form = *Box::from_raw(form);
species.as_mut().add_form(CStr::from_ptr(name).into(), form)
}
#[no_mangle]
unsafe extern "C" fn species_get_form(species: ExternPointer<Species>, name: BorrowedPtr<c_char>) -> BorrowedPtr<Form> {
let form = species.as_ref().get_form(&CStr::from_ptr(name).into());
if let Some(form) = form {
Arc::as_ptr(form)
} else {
std::ptr::null()
}
}

View File

@@ -0,0 +1,106 @@
use crate::ffi::{ExternPointer, OwnedPtr};
use crate::static_data::{StaticStatisticSet, Statistic, StatisticSet};
use std::ptr::drop_in_place;
macro_rules! statistic_set {
($num_type:ident) => {
paste::paste!{
#[no_mangle]
extern "C" fn [<statistic_set_ $num_type _new>](
hp: $num_type,
attack: $num_type,
defense: $num_type,
special_attack: $num_type,
special_defense: $num_type,
speed: $num_type,
) -> OwnedPtr<StatisticSet<$num_type>> {
Box::into_raw(Box::new(StatisticSet::new(
hp,
attack,
defense,
special_attack,
special_defense,
speed,
)))
}
#[no_mangle]
unsafe extern "C" fn [<statistic_set_ $num_type _drop>](ptr: OwnedPtr<StatisticSet<$num_type>>) {
drop_in_place(ptr)
}
#[no_mangle]
extern "C" fn [<statistic_set_ $num_type _get_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic) -> $num_type {
ptr.as_ref().get_stat(stat)
}
#[no_mangle]
extern "C" fn [<statistic_set_ $num_type _set_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
ptr.as_ref().set_stat(stat, value)
}
#[no_mangle]
extern "C" fn [<statistic_set_ $num_type _increase_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
ptr.as_ref().increase_stat(stat, value)
}
#[no_mangle]
extern "C" fn [<statistic_set_ $num_type _decrease_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
ptr.as_ref().decrease_stat(stat, value)
}
}
};
}
statistic_set!(u8);
statistic_set!(u16);
statistic_set!(u32);
statistic_set!(i8);
statistic_set!(i16);
statistic_set!(i32);
macro_rules! static_statistic_set {
($num_type:ident) => {
paste::paste!{
#[no_mangle]
extern "C" fn [<static_statistic_set_ $num_type _new>](
hp: $num_type,
attack: $num_type,
defense: $num_type,
special_attack: $num_type,
special_defense: $num_type,
speed: $num_type,
) -> OwnedPtr<StaticStatisticSet<$num_type>> {
Box::into_raw(Box::new(StaticStatisticSet::new(
hp,
attack,
defense,
special_attack,
special_defense,
speed,
)))
}
#[no_mangle]
unsafe extern "C" fn [<static_statistic_set_ $num_type _drop>](ptr: OwnedPtr<StaticStatisticSet<$num_type>>) {
drop_in_place(ptr)
}
#[no_mangle]
extern "C" fn [<static_statistic_set_ $num_type _get_stat>](ptr: ExternPointer<StaticStatisticSet<$num_type>>, stat: Statistic) -> $num_type {
ptr.as_ref().get_stat(stat)
}
}
};
}
static_statistic_set!(u8);
static_statistic_set!(u16);
static_statistic_set!(u32);
static_statistic_set!(i8);
static_statistic_set!(i16);
static_statistic_set!(i32);