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 { 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 = 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) { drop_in_place(ptr) } #[no_mangle] unsafe extern "C" fn move_data_name(ptr: ExternPointer) -> OwnedPtr { 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) -> BorrowedPtr { 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, 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, parameters: *mut OwnedPtr, parameters_length: usize, ) -> OwnedPtr { 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) { drop_in_place(ptr) } ffi_getter!(SecondaryEffect, chance, f32); #[no_mangle] unsafe extern "C" fn secondary_effect_effect_name(ptr: ExternPointer) -> OwnedPtr { CString::new(ptr.as_ref().effect_name().str()).unwrap().into_raw() } #[no_mangle] unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer) -> usize { ptr.as_ref().parameters().len() } #[no_mangle] unsafe extern "C" fn secondary_effect_parameter_get( ptr: ExternPointer, index: usize, ) -> BorrowedPtr { if let Some(v) = ptr.as_ref().parameters().get(index) { v as *const EffectParameter } else { std::ptr::null() } }