use crate::ffi::{ ffi_arc_dyn_getter, ffi_arc_stringkey_getter, BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr, }; use crate::static_data::{Form, Gender, Species, SpeciesImpl}; use crate::{Random, StringKey}; use hashbrown::HashSet; use std::ffi::{c_char, CStr}; use std::ptr::drop_in_place; use std::sync::Arc; /// Creates a new species. #[no_mangle] unsafe extern "C" fn species_new( id: u16, name: BorrowedPtr, gender_rate: f32, growth_rate: BorrowedPtr, capture_rate: u8, default_form: OwnedPtr>, flags: *const *const c_char, flags_length: usize, ) -> IdentifiablePointer> { 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 = HashSet::with_capacity(flags_length); for flag in flags { flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into()); } let a: Arc = Arc::new(SpeciesImpl::new( id, &name, gender_rate, &growth_rate, capture_rate, default_form.as_ref().unwrap().clone(), flags_set, )); a.into() } /// Drop a reference to the species. #[no_mangle] unsafe extern "C" fn species_drop(ptr: OwnedPtr>) { drop_in_place(ptr); } ffi_arc_dyn_getter!(Species, id, u16); ffi_arc_stringkey_getter!(Species, name); ffi_arc_dyn_getter!(Species, gender_rate, f32); ffi_arc_stringkey_getter!(Species, growth_rate); ffi_arc_dyn_getter!(Species, capture_rate, u8); /// Adds a new form to the species. #[no_mangle] unsafe extern "C" fn species_add_form( mut species: ExternPointer>, name: BorrowedPtr, form: OwnedPtr>, ) { let form = form.as_ref().unwrap().clone(); species.as_mut().add_form(CStr::from_ptr(name).into(), form) } /// Gets a form by name. #[no_mangle] unsafe extern "C" fn species_get_form( species: ExternPointer>, name: BorrowedPtr, ) -> IdentifiablePointer> { let form = species.as_ref().get_form(&CStr::from_ptr(name).into()); if let Some(form) = form { form.into() } else { IdentifiablePointer::none() } } /// Gets a form by name. #[no_mangle] unsafe extern "C" fn species_get_random_gender(species: ExternPointer>, seed: u64) -> Gender { let mut rand = Random::new(seed as u128); species.as_ref().get_random_gender(&mut rand) }