PkmnLib_rs/src/ffi/static_data/libraries/nature_library.rs

85 lines
2.8 KiB
Rust

use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
use crate::static_data::{Nature, NatureLibrary, NatureLibraryImpl};
use crate::{PkmnError, Random};
use anyhow::anyhow;
use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place;
use std::sync::Arc;
/// Creates a new nature library with a given capacity.
#[no_mangle]
extern "C" fn nature_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn NatureLibrary>> {
let b: Box<dyn NatureLibrary> = Box::new(NatureLibraryImpl::new(capacity));
b.into()
}
/// Drop a nature library.
#[no_mangle]
unsafe extern "C" fn nature_library_drop(ptr: OwnedPtr<Box<dyn NatureLibrary>>) {
drop_in_place(ptr);
}
/// Adds a new nature with name to the library.
#[no_mangle]
unsafe extern "C" fn nature_library_load_nature(
mut ptr: ExternPointer<Box<dyn NatureLibrary>>,
name: BorrowedPtr<c_char>,
nature: OwnedPtr<Arc<dyn Nature>>,
) -> NativeResult<()> {
let nature = nature.as_ref().ok_or(PkmnError::NullReference);
match nature {
Ok(nature) => {
ptr.as_mut().load_nature(CStr::from_ptr(name).into(), nature.clone());
NativeResult::ok(())
}
Err(e) => NativeResult::err(e.into()),
}
}
/// Gets a nature by name.
#[no_mangle]
unsafe extern "C" fn nature_library_get_nature(
ptr: ExternPointer<Box<dyn NatureLibrary>>,
name: BorrowedPtr<c_char>,
) -> IdentifiablePointer<Arc<dyn Nature>> {
if let Some(nature) = ptr.as_ref().get_nature(&CStr::from_ptr(name).into()) {
nature.into()
} else {
IdentifiablePointer::none()
}
}
/// Gets a random nature.
#[no_mangle]
unsafe extern "C" fn nature_library_get_random_nature(
ptr: ExternPointer<Box<dyn NatureLibrary>>,
seed: u64,
) -> NativeResult<IdentifiablePointer<Arc<dyn Nature>>> {
let mut rand = Random::new(seed as u128);
match ptr.as_ref().get_random_nature(&mut rand) {
Ok(nature) => NativeResult::ok(nature.into()),
Err(e) => NativeResult::err(e),
}
}
/// Finds a nature name by nature.
#[no_mangle]
unsafe extern "C" fn nature_library_get_nature_name(
ptr: ExternPointer<Box<dyn NatureLibrary>>,
nature: BorrowedPtr<Arc<dyn Nature>>,
) -> NativeResult<OwnedPtr<c_char>> {
match nature.as_ref() {
Some(nature) => {
let name = ptr.as_ref().get_nature_name(nature);
match name {
Ok(name) => match CString::new(name.str()) {
Ok(cstr) => NativeResult::ok(cstr.into_raw()),
Err(_) => NativeResult::err(anyhow!("Failed to convert nature name to C string")),
},
Err(e) => NativeResult::err(e),
}
}
None => NativeResult::err(PkmnError::NullReference.into()),
}
}