use crate::ffi::ffi_handle::FFIHandle; use crate::ffi::{ ffi_handle_arc_dyn_getter, ffi_handle_arc_stringkey_getter, FFIResult, FromFFIHandle, NonOwnedPtrString, }; use crate::static_data::{Form, Gender, Species, SpeciesImpl}; use crate::{PkmnError, Random, StringKey}; use hashbrown::HashSet; use std::ffi::{c_char, CStr}; use std::sync::Arc; /// Creates a new species. #[no_mangle] unsafe extern "C" fn species_new( id: u16, name: NonOwnedPtrString, gender_rate: f32, growth_rate: NonOwnedPtrString, capture_rate: u8, default_form: FFIHandle>, flags: *const *const c_char, flags_length: usize, ) -> FFIResult>> { let name: StringKey = match CStr::from_ptr(name).to_str() { Ok(name) => name.into(), Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()), }; let growth_rate: StringKey = match CStr::from_ptr(growth_rate).to_str() { Ok(growth_rate) => growth_rate.into(), Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()), }; let flags = std::slice::from_raw_parts(flags, flags_length); let mut flags_set: HashSet = HashSet::with_capacity(flags_length); for flag in flags { let flag = match CStr::from_ptr(*flag).to_str() { Ok(flag) => flag, Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()), }; flags_set.insert(flag.into()); } let default_form = if default_form.is_none() { return FFIResult::err(PkmnError::NullReference.into()); } else { default_form.from_ffi_handle() }; let a: Arc = Arc::new(SpeciesImpl::new( id, &name, gender_rate, &growth_rate, capture_rate, default_form.clone(), flags_set, )); FFIResult::ok(FFIHandle::get_handle(a.into())) } ffi_handle_arc_dyn_getter!(Species, id, u16); ffi_handle_arc_stringkey_getter!(Species, name); ffi_handle_arc_dyn_getter!(Species, gender_rate, f32); ffi_handle_arc_stringkey_getter!(Species, growth_rate); ffi_handle_arc_dyn_getter!(Species, capture_rate, u8); /// Adds a new form to the species. #[no_mangle] unsafe extern "C" fn species_add_form( species: FFIHandle>, name: NonOwnedPtrString, form: FFIHandle>, ) -> FFIResult<()> { let form = if form.is_none() { return FFIResult::err(PkmnError::NullReference.into()); } else { form.from_ffi_handle() }; species.from_ffi_handle().add_form(CStr::from_ptr(name).into(), form); FFIResult::ok(()) } /// Gets a form by name. #[no_mangle] unsafe extern "C" fn species_get_form( species: FFIHandle>, name: NonOwnedPtrString, ) -> FFIHandle> { let form = species.from_ffi_handle().get_form(&CStr::from_ptr(name).into()); if let Some(form) = form { FFIHandle::get_handle(form.into()) } else { FFIHandle::none() } } /// Gets a form by name. #[no_mangle] unsafe extern "C" fn species_get_random_gender(species: FFIHandle>, seed: u64) -> Gender { let mut rand = Random::new(seed as u128); species.from_ffi_handle().get_random_gender(&mut rand) }