diff --git a/crates/byondapi-rs-test/Cargo.toml b/crates/byondapi-rs-test/Cargo.toml index aa537a1..8802a6c 100644 --- a/crates/byondapi-rs-test/Cargo.toml +++ b/crates/byondapi-rs-test/Cargo.toml @@ -11,5 +11,5 @@ crate-type = ["cdylib"] [dependencies] byondapi = { path = "../byondapi-rs" } byondapi-sys = { path = "../byondapi-sys" } -tempfile = "3.7.0" +tempfile = "3.8.0" test-cdylib = "1.1.0" diff --git a/crates/byondapi-rs-test/dm_project/dm_project.dme b/crates/byondapi-rs-test/dm_project/dm_project.dme index 3177d19..8d36135 100644 --- a/crates/byondapi-rs-test/dm_project/dm_project.dme +++ b/crates/byondapi-rs-test/dm_project/dm_project.dme @@ -56,13 +56,15 @@ if(O.name != ret) throw EXCEPTION("Call proc failed, expected rust to return 'test name' but got '[ret]'") +/datum/data + var/name = "test name" + /test/proc/test_readwrite_var() - var/obj/O = new() - O.name = "test name" + var/datum/data/stub = new() - var/ret = call_ext("byondapi_test.dll", "byond:test_readwrite_var")(O) + var/ret = call_ext("byondapi_test.dll", "byond:test_readwrite_var")(stub) - if(O.name != ret) + if(stub.name != ret) throw EXCEPTION("Call proc failed, expected rust to return 'test name' but got '[ret]'") /test/proc/test_list_push() diff --git a/crates/byondapi-rs-test/src/lib.rs b/crates/byondapi-rs-test/src/lib.rs index 57c0d92..ecb51e9 100644 --- a/crates/byondapi-rs-test/src/lib.rs +++ b/crates/byondapi-rs-test/src/lib.rs @@ -102,8 +102,8 @@ pub unsafe extern "C" fn test_readwrite_var( let args = parse_args(argc, argv); let object = &args[0]; - match object.read_var("name") { - Ok(res) => res, + match object.read_string("name") { + Ok(res) => res.try_into().unwrap(), Err(e) => format!("{:#?}", e).try_into().unwrap(), } } diff --git a/crates/byondapi-rs-test/tests/test.rs b/crates/byondapi-rs-test/tests/test.rs index 23dd391..6176193 100644 --- a/crates/byondapi-rs-test/tests/test.rs +++ b/crates/byondapi-rs-test/tests/test.rs @@ -6,7 +6,6 @@ use std::{ use tempfile::TempDir; #[test] -#[ignore] #[cfg(windows)] fn test_byondapi_with_dreamdaemon() { let dll = build_dylib(); diff --git a/crates/byondapi-rs/Cargo.toml b/crates/byondapi-rs/Cargo.toml index 24b58f7..42724b7 100644 --- a/crates/byondapi-rs/Cargo.toml +++ b/crates/byondapi-rs/Cargo.toml @@ -15,8 +15,9 @@ exclude = [".vscode/*"] [dependencies] byondapi-sys = { path = "../byondapi-sys", version = "0.10.1" } lazy_static = "1.4.0" -libloading = "0.8.0" -walkdir = "2.3.3" +libloading = "0.8.1" +walkdir = "2.4.0" +inventory = "0.3.12" [features] default = ["byond-515-1611"] diff --git a/crates/byondapi-rs/src/byond_string.rs b/crates/byondapi-rs/src/byond_string.rs new file mode 100644 index 0000000..ca83c3e --- /dev/null +++ b/crates/byondapi-rs/src/byond_string.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; +use crate::static_global::byond; +use crate::Error; +use std::ffi::{CStr, CString}; + +pub fn str_id_of>>(string: T) -> Result { + let c_string = CString::new(string).unwrap(); + str_id_of_cstr(c_string.as_c_str()) +} + +pub fn str_id_of_cstr(string: &CStr) -> Result { + let res = unsafe { byond().Byond_GetStrId(string.as_ptr()) }; + if res == u2c::MAX as u32 { + return Err(Error::NonExistentString); + } + Ok(res) +} diff --git a/crates/byondapi-rs/src/error.rs b/crates/byondapi-rs/src/error.rs index 5e2eaf5..66bb6ab 100644 --- a/crates/byondapi-rs/src/error.rs +++ b/crates/byondapi-rs/src/error.rs @@ -17,10 +17,19 @@ pub enum Error { UnknownByondError, /// Thrown by us when we know this call will panic internally because of the version NotAvailableForThisByondVersion, - /// Thrown by us when we know this type does not have a ref + /// Thrown by us when we know this type does not have a refnumber NotReferencable, - /// Thrown by us when we know this type is not indexable because it's not a list + /// Thrown by us when we know this type is not a list, and we're expecting one NotAList, + /// Thrown by us when we know this type is not a string, and we're expecting one + NotAString, + /// Thrown by us when we know this type is not a number, and we're expecting one + NotANum, + /// Thrown by us when we know this type is not a pointer, and we're expecting one + NotAPtr, + /// Thrown by [`crate::byond_string::str_id_of_cstr`] when the string doesn't exist in + /// byondland + NonExistentString, } impl Error { @@ -46,7 +55,11 @@ impl std::fmt::Display for Error { "This call is not available on current version of the api" ), Self::NotReferencable => write!(f, "Cannot get a ref from this value"), - Self::NotAList => write!(f, "Cannot index into value, value is not a list"), + Self::NotAList => write!(f, "Value is not a list"), + Self::NotAString => write!(f, "Value is not a string"), + Self::NotANum => write!(f, "Value is not a number"), + Self::NotAPtr => write!(f, "Value is not a pointer"), + Self::NonExistentString => write!(f, "String id not found"), } } } diff --git a/crates/byondapi-rs/src/global_call.rs b/crates/byondapi-rs/src/global_call.rs new file mode 100644 index 0000000..9771476 --- /dev/null +++ b/crates/byondapi-rs/src/global_call.rs @@ -0,0 +1,46 @@ +use crate::prelude::*; +use crate::static_global::byond; +use crate::Error; + +use std::ffi::CString; + +/// Calls a global proc. +/// +/// Implicitly set waitfor=0, will never block. +pub fn call_global>>(name: T, args: &[ByondValue]) -> Result { + let c_string = CString::new(name).unwrap(); + let c_str = c_string.as_c_str(); + + let str_id = unsafe { byond().Byond_GetStrId(c_str.as_ptr()) }; + if str_id == crate::sys::u2c::MAX as u32 { + return Err(Error::InvalidProc); + } + let ptr = args.as_ptr(); + let mut new_value = ByondValue::new(); + unsafe { + map_byond_error!(byond().Byond_CallGlobalProcByStrId( + str_id, + ptr.cast(), + args.len() as u32, + &mut new_value.0 + ))?; + } + Ok(new_value) +} + +/// Calls a global proc by its string id. +/// +/// Implicitly set waitfor=0, will never block. +pub fn call_global_id(name: u4c, args: &[ByondValue]) -> Result { + let ptr = args.as_ptr(); + let mut new_value = ByondValue::new(); + unsafe { + map_byond_error!(byond().Byond_CallGlobalProcByStrId( + name, + ptr.cast(), + args.len() as u32, + &mut new_value.0 + ))?; + } + Ok(new_value) +} diff --git a/crates/byondapi-rs/src/lib.rs b/crates/byondapi-rs/src/lib.rs index 7c6868f..221bb0e 100644 --- a/crates/byondapi-rs/src/lib.rs +++ b/crates/byondapi-rs/src/lib.rs @@ -1,11 +1,16 @@ mod static_global; +///Plugin init system +pub use inventory; + #[macro_use] pub mod error; #[cfg(feature = "byond-515-1611")] pub mod map; pub use error::Error; +pub mod byond_string; +pub mod global_call; pub mod list; pub mod prelude; pub mod typecheck_trait; @@ -26,3 +31,13 @@ pub unsafe fn parse_args( pub mod sys { pub use byondapi_sys::*; } + +inventory::collect!(InitFunc); + +///This function will be ran to set up things before the lib is loaded +///The lib is only loaded when any byondapi functions are called from byond +///To submit a function (func) to be ran by byondapi on it's libload, do: +///``` +///byondapi::inventory::submit! {InitFunc(func)} +///``` +pub struct InitFunc(pub fn() -> ()); diff --git a/crates/byondapi-rs/src/list.rs b/crates/byondapi-rs/src/list.rs index dd8de98..889ed6d 100644 --- a/crates/byondapi-rs/src/list.rs +++ b/crates/byondapi-rs/src/list.rs @@ -32,6 +32,20 @@ impl ByondValueList { pub fn is_empty(&self) -> bool { self.len() == 0 } + + pub fn into_value(&self) -> Result { + // The API must be called in this order: + // ByondValue_Init(&value) // Initializes the value + // Byond_CreateList(&value) // Creates a list() inside DM + // Byond_WriteList(&value, &list) // Copies the CByondList into the dm list() + let new_value = ByondValue::new_list().unwrap(); + + unsafe { + map_byond_error!(byond().Byond_WriteList(&new_value.0, &self.0))?; + } + + Ok(new_value) + } } /// # Accessors @@ -149,41 +163,27 @@ impl Default for ByondValueList { } } -impl TryFrom<&ByondValue> for ByondValueList { +impl TryFrom for ByondValueList { type Error = Error; - fn try_from(value: &ByondValue) -> Result { - let mut new_list = ByondValueList::new(); - - unsafe { map_byond_error!(byond().Byond_ReadList(&value.0, &mut new_list.0))? } - - Ok(new_list) + fn try_from(value: ByondValue) -> Result { + value.get_list() } } -impl TryFrom<&ByondValueList> for ByondValue { +impl TryFrom<&ByondValue> for ByondValueList { type Error = Error; - fn try_from(value: &ByondValueList) -> Result { - // The API must be called in this order: - // ByondValue_Init(&value) // Initializes the value - // Byond_CreateList(&value) // Creates a list() inside DM - // Byond_WriteList(&value, &list) // Copies the CByondList into the dm list() - let new_value = ByondValue::new_list().unwrap(); - - unsafe { - map_byond_error!(byond().Byond_WriteList(&new_value.0, &value.0))?; - } - - Ok(new_value) + fn try_from(value: &ByondValue) -> Result { + value.get_list() } } -impl TryFrom for ByondValueList { +impl TryFrom<&ByondValueList> for ByondValue { type Error = Error; - fn try_from(value: ByondValue) -> Result { - (&value).try_into() + fn try_from(value: &ByondValueList) -> Result { + value.into_value() } } @@ -191,7 +191,7 @@ impl TryFrom for ByondValue { type Error = Error; fn try_from(value: ByondValueList) -> Result { - (&value).try_into() + value.into_value() } } @@ -209,18 +209,6 @@ impl TryFrom<&[ByondValue]> for ByondValueList { } } -impl<'a> From<&'a ByondValueList> for &'a [ByondValue] { - fn from(value: &'a ByondValueList) -> Self { - value - } -} - -impl<'a> From<&'a mut ByondValueList> for &'a mut [ByondValue] { - fn from(value: &'a mut ByondValueList) -> Self { - value - } -} - /// Clones the list into a vec impl From for Vec { fn from(value: ByondValueList) -> Self { diff --git a/crates/byondapi-rs/src/static_global.rs b/crates/byondapi-rs/src/static_global.rs index 39378b8..796fcee 100644 --- a/crates/byondapi-rs/src/static_global.rs +++ b/crates/byondapi-rs/src/static_global.rs @@ -1,5 +1,8 @@ #[cfg(target_os = "windows")] -pub fn init_lib() -> byondapi_sys::ByondApi { +fn init_lib() -> byondapi_sys::ByondApi { + for func in inventory::iter:: { + func.0(); + } let library = { let result = libloading::os::windows::Library::open_already_loaded("byondcore.dll"); @@ -21,7 +24,10 @@ pub fn init_lib() -> byondapi_sys::ByondApi { } #[cfg(target_os = "linux")] -pub fn init_lib() -> byondapi_sys::ByondApi { +fn init_lib() -> byondapi_sys::ByondApi { + for func in inventory::iter:: { + func.0(); + } let library = libloading::os::unix::Library::this(); match unsafe { byondapi_sys::ByondApi::init_from_library(library) } { Err(e) => { diff --git a/crates/byondapi-rs/src/value/conversion.rs b/crates/byondapi-rs/src/value/conversion.rs index 79f7608..9adf6c1 100644 --- a/crates/byondapi-rs/src/value/conversion.rs +++ b/crates/byondapi-rs/src/value/conversion.rs @@ -1,10 +1,9 @@ -use std::ffi::{CStr, CString}; +use std::ffi::CString; use super::ByondValue; -use crate::{static_global::byond, typecheck_trait::ByondTypeCheck, Error}; +use crate::Error; // From Impls - impl From for ByondValue { fn from(value: bool) -> Self { if value { @@ -38,11 +37,27 @@ impl TryFrom for ByondValue { } // TryFrom ByondValue -> x impls +impl TryFrom for bool { + type Error = Error; + + fn try_from(value: ByondValue) -> Result { + value.get_bool() + } +} + +impl TryFrom<&ByondValue> for bool { + type Error = Error; + + fn try_from(value: &ByondValue) -> Result { + value.get_bool() + } +} + impl TryFrom for f32 { type Error = Error; fn try_from(value: ByondValue) -> Result { - (&value).try_into() + value.get_number() } } @@ -50,11 +65,7 @@ impl TryFrom<&ByondValue> for f32 { type Error = Error; fn try_from(value: &ByondValue) -> Result { - if value.is_num() { - Ok(unsafe { byond().ByondValue_GetNum(&value.0) }) - } else { - Err(Error::InvalidConversion) - } + value.get_number() } } @@ -62,7 +73,7 @@ impl TryFrom for CString { type Error = Error; fn try_from(value: ByondValue) -> Result { - value.try_into() + value.get_cstring() } } @@ -70,13 +81,7 @@ impl TryFrom<&ByondValue> for CString { type Error = Error; fn try_from(value: &ByondValue) -> Result { - if value.is_str() { - let ptr = unsafe { byond().ByondValue_GetStr(&value.0) }; - let cstr = unsafe { CStr::from_ptr(ptr) }; - Ok(cstr.to_owned()) - } else { - Err(Error::InvalidConversion) - } + value.get_cstring() } } @@ -84,7 +89,7 @@ impl TryFrom for String { type Error = Error; fn try_from(value: ByondValue) -> Result { - value.try_into() + value.get_string() } } @@ -92,7 +97,6 @@ impl TryFrom<&ByondValue> for String { type Error = Error; fn try_from(value: &ByondValue) -> Result { - let cstring: CString = value.try_into()?; - cstring.into_string().map_err(|_| Error::NonUtf8String) + value.get_string() } } diff --git a/crates/byondapi-rs/src/value/functions.rs b/crates/byondapi-rs/src/value/functions.rs index 3062158..829b14e 100644 --- a/crates/byondapi-rs/src/value/functions.rs +++ b/crates/byondapi-rs/src/value/functions.rs @@ -1,9 +1,12 @@ -use std::ffi::CString; +use std::ffi::{CStr, CString}; use byondapi_sys::{u4c, ByondValueType, CByondValue}; use super::ByondValue; -use crate::{map::byond_length, static_global::byond, typecheck_trait::ByondTypeCheck, Error}; +use crate::{ + map::byond_length, prelude::ByondValueList, static_global::byond, + typecheck_trait::ByondTypeCheck, Error, +}; /// # Compatibility with the C++ API impl ByondValue { @@ -13,19 +16,59 @@ impl ByondValue { std::mem::replace(&mut self.0, unsafe { std::mem::zeroed() }) } + /// Try to get a [`bool`] or fail if this isn't a number type + pub fn get_bool(&self) -> Result { + self.get_number().map(|num| match num as u32 { + (1..) => true, + 0 => false, + }) + } + /// Try to get an [`f32`] or fail if this isn't a number type pub fn get_number(&self) -> Result { - self.try_into() + if self.is_num() { + Ok(unsafe { byond().ByondValue_GetNum(&self.0) }) + } else { + Err(Error::NotANum) + } } /// Try to get a [`CString`] or fail if this isn't a string type pub fn get_cstring(&self) -> Result { - self.try_into() + self.get_cstr().map(|cstr| cstr.to_owned()) + } + + /// Try to get a [`CStr`] or fail if this isn't a string type + pub fn get_cstr<'a>(&'a self) -> Result<&'a CStr, Error> { + if self.is_str() { + let ptr = unsafe { byond().ByondValue_GetStr(&self.0) }; + let cstr = unsafe { CStr::from_ptr(ptr) }; + Ok(cstr) + } else { + Err(Error::NotAString) + } } /// Try to get a [`String`] or fail if this isn't a string type or isn't utf8 pub fn get_string(&self) -> Result { - self.try_into() + self.get_cstring().map(|cstring| { + cstring + .to_str() + .map_err(|_| Error::NonUtf8String) + .map(str::to_owned) + })? + } + + /// Try to get a [`crate::prelude::ByondValueList`] or fail if this isn't a string type or isn't utf8 + pub fn get_list(&self) -> Result { + if !self.is_list() { + return Err(Error::NotAList); + } + let mut new_list = ByondValueList::new(); + + unsafe { map_byond_error!(byond().Byond_ReadList(&self.0, &mut new_list.0))? } + + Ok(new_list) } /// Get the underlying ref number to this value @@ -35,6 +78,11 @@ impl ByondValue { } Ok(unsafe { byond().ByondValue_GetRef(&self.0) }) } + + /// Get the string id of this value, fail if this isn't a string + pub fn get_strid(&self) -> Result { + crate::byond_string::str_id_of_cstr(self.get_cstr()?) + } } /// # In-place modifiers @@ -61,6 +109,9 @@ impl ByondValue { impl ByondValue { /// Read a variable through the ref. Fails if this isn't a ref type. pub fn read_var>>(&self, name: T) -> Result { + if self.is_num() || self.is_str() || self.is_ptr() || self.is_null() || self.is_list() { + return Err(Error::NotReferencable); + } let c_string = CString::new(name).unwrap(); let c_str = c_string.as_c_str(); @@ -101,7 +152,7 @@ impl ByondValue { let c_str = c_string.as_c_str(); let str_id = unsafe { byond().Byond_GetStrId(c_str.as_ptr()) }; - if str_id == 0 { + if str_id == crate::sys::u2c::MAX as u32 { return Err(Error::InvalidProc); } @@ -121,6 +172,47 @@ impl ByondValue { } } +/// # Accessors by ids +impl ByondValue { + /// Read a variable through the ref. Fails if this isn't a ref type, or the id is invalid. + pub fn read_var_id(&self, name: u4c) -> Result { + let mut new_value = ByondValue::new(); + unsafe { + map_byond_error!(byond().Byond_ReadVarByStrId(&self.0, name, &mut new_value.0))?; + } + + Ok(new_value) + } + + /// Write to a variable through the ref. Fails if this isn't a ref type, or the id is invalid. + pub fn write_var_id(&mut self, name: u4c, other: &ByondValue) -> Result<(), Error> { + unsafe { map_byond_error!(byond().Byond_WriteVarByStrId(&self.0, name, &other.0)) } + } + + /// Call a proc using self as src. Fails if this isn't a ref type, or the id is invalid. + /// + /// Implicitly set waitfor=0, will never block. + /// + /// # WARNING FOR BYOND 515.1609 and 515.1610 + /// This is treated as verb name, so underscores are replaced with spaces. + /// For example `/obj/proc/get_name` would have to be called as `obj.call("get name")`. + pub fn call_id(&self, name: u4c, args: &[ByondValue]) -> Result { + let ptr = args.as_ptr(); + let mut new_value = ByondValue::new(); + unsafe { + map_byond_error!(byond().Byond_CallProcByStrId( + &self.0, + name, + ptr as *const byondapi_sys::CByondValue, + args.len() as u32, + &mut new_value.0 + ))?; + } + + Ok(new_value) + } +} + /// # List operations by key instead of indices (why are they even here lumlum?????) impl ByondValue { /// Reads a value by key through the ref. Fails if this isn't a list. @@ -183,12 +275,12 @@ impl ByondValue { impl ByondValue { /// Reads a number through the ref. Fails if this isn't a ref type or this isn't a number. pub fn read_number>>(&self, name: T) -> Result { - self.read_var(name)?.try_into() + self.read_var(name)?.get_number() } /// Reads a string through the ref. Fails if this isn't a ref type or this isn't a string. pub fn read_string>>(&self, name: T) -> Result { - self.read_var(name)?.try_into() + self.read_var(name)?.get_string() } /// Reads a list through the ref. Fails if this isn't a ref type or this isn't a list. @@ -200,7 +292,7 @@ impl ByondValue { } /// Iterates through the assoc values of the list if this value is a list, if the value isn't a list then it returns an error. - /// Non assoc lists will have the second field of the tuple be None always, and the value in the first field + /// Non assoc lists will have the second field of the tuple be null /// (key, value) for proper assoc lists pub fn iter(&self) -> Result + '_, Error> { if !self.is_list() { @@ -213,6 +305,41 @@ impl ByondValue { ctr: 1, }) } + pub fn values(&self) -> Result + '_, Error> { + if !self.is_list() { + return Err(Error::NotAList); + } + let len: f32 = byond_length(self)?.try_into()?; + Ok(ValueIterator { + value: self, + len: len as u32, + ctr: 1, + }) + } +} + +struct ValueIterator<'a> { + value: &'a ByondValue, + len: u32, + ctr: u32, +} +impl<'a> Iterator for ValueIterator<'a> { + type Item = ByondValue; + fn next(&mut self) -> Option { + if self.ctr <= self.len { + let value = self + .value + .read_list_index_internal(&ByondValue::from(self.ctr as f32)) + .ok()?; + self.ctr += 1; + Some(value) + } else { + None + } + } + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.len as usize)) + } } struct ListIterator<'a> { diff --git a/crates/byondapi-rs/src/value/pointer.rs b/crates/byondapi-rs/src/value/pointer.rs index ee84216..83fd15d 100644 --- a/crates/byondapi-rs/src/value/pointer.rs +++ b/crates/byondapi-rs/src/value/pointer.rs @@ -34,7 +34,7 @@ impl TryFrom for ByondValuePointer { if value.is_ptr() { Ok(Self(value)) } else { - Err(Error::InvalidConversion) + Err(Error::NotAPtr) } } } diff --git a/crates/byondapi-rs/src/value/trait_impls.rs b/crates/byondapi-rs/src/value/trait_impls.rs index d09d7d0..7483fb9 100644 --- a/crates/byondapi-rs/src/value/trait_impls.rs +++ b/crates/byondapi-rs/src/value/trait_impls.rs @@ -1,20 +1,17 @@ use super::ByondValue; use crate::static_global::byond; -use std::{fmt::Debug, mem::MaybeUninit}; +use std::fmt::Debug; // Memory handling impl Clone for ByondValue { fn clone(&self) -> Self { - let mut new_inner = MaybeUninit::uninit(); + let mut cloned_value = ByondValue::null(); - let new_inner = unsafe { - // Safety: new_inner is going to an initialization function, it will only write to the pointer. - byond().ByondValue_CopyFrom(new_inner.as_mut_ptr(), &self.0); - // Safety: ByondValue_Init will have initialized the new_inner. - new_inner.assume_init() + unsafe { + byond().ByondValue_CopyFrom(&mut cloned_value.0, &self.0); }; - Self(new_inner) + cloned_value } } diff --git a/crates/byondapi-sys/Cargo.toml b/crates/byondapi-sys/Cargo.toml index 70e4f28..5b230d3 100644 --- a/crates/byondapi-sys/Cargo.toml +++ b/crates/byondapi-sys/Cargo.toml @@ -17,15 +17,16 @@ default-target = "i686-unknown-linux-gnu" targets = [] # Do not build the doc with any other target than the default. [dependencies] -libloading = "0.8.0" +libloading = "0.8.1" [build-dependencies] -bindgen = "0.66.1" +bindgen = "0.68.1" rustc_version = "0.4.0" -walkdir = "2.3.3" +walkdir = "2.4.0" [features] -default = ["byond-515-1611"] +default = ["byond-515-1617"] +byond-515-1617 = [] byond-515-1611 = [] byond-515-1610 = [] byond-515-1609 = [] diff --git a/crates/byondapi-sys/headers/515-1617/byondapi.h b/crates/byondapi-sys/headers/515-1617/byondapi.h new file mode 100644 index 0000000..a4b3d80 --- /dev/null +++ b/crates/byondapi-sys/headers/515-1617/byondapi.h @@ -0,0 +1,299 @@ +#ifndef BYONDAPI_H +#define BYONDAPI_H + +/* + BYOND public API version 515.1609 + + Because for some reason nobody can get their ducks in a row, all of the + exported functions from byondcore.dll/libbyond.so are limited to C + conventions only. A header and source file for C++ wrappers is available + for inclusion in your projects. + */ + +#if defined(WIN32) || defined(WIN64) +#define IS_WINDOWS +#else +#define IS_LINUX +#endif + + +// See https://github.com/cpredef/predef/blob/master/Architectures.md +#if defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__X86__) +#define _X86 +#define _X86ORX64 +#define DM_32BIT +#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(_WIN64) || defined(WIN64) +#define _X64 +#define _X86ORX64 +#define DM_64BIT +#elif defined(__arm__) || defined(_M_ARM) +#define _ARM +#if defined(__LP64__) || defined(_LP64) +#define DM_64BIT +#else +#define DM_32BIT +#endif +#endif + + + +/*types*/ +typedef unsigned char u1c; +typedef signed char s1c; +typedef unsigned short u2c; +typedef signed short s2c; +#ifdef DM_64BIT +typedef unsigned int u4c; +typedef signed int s4c; +#else +typedef unsigned long u4c; +typedef signed long s4c; +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 s8c; + typedef unsigned __int64 u8c; +#else + typedef long long int s8c; + typedef unsigned long long int u8c; +#endif + +union u4cOrPointer { + u4c num; + void *ptr; +}; + +#ifdef __GNUC__ +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +#define GCC_VERSION 0 +#endif + + +// determine if move-constructor and move-assignment are supported +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#define _SUPPORT_MOVES +#elif defined(__GNUC__) && GCC_VERSION >= 50000 +#define _SUPPORT_MOVES +#endif + + +#define u1cMASK ((u1c)0xff) +#define u2cMASK ((u2c)0xffff) +#define u3cMASK ((u4c)0xffffffL) +#define u4cMASK ((u4c)0xffffffffL) + +#define u1cMAX u1cMASK +#define u2cMAX u2cMASK +#define u3cMAX u3cMASK +#define u4cMAX u4cMASK + +#define s1cMAX 0x7f +#define s1cMIN (-0x7f) +#define s2cMAX 0x7fff +#define s2cMIN (-0x7fff) +#define s4cMAX 0x7fffffffL +#define s4cMIN (-0x7fffffffL) + +#define NONE u2cMAX +#define NOCH u1cMAX + +/* dll export stuff */ +#ifdef WIN32 +#define DUNGPUB __declspec(dllimport) +#define BYOND_EXPORT __declspec(dllexport) // for functions in user-defined DLLs for use with call_ext() +#else // unix/g++, combine with -fvisibility=hidden to hide non-exported symbols +#define DUNGPUB +#define BYOND_EXPORT __attribute__ ((visibility("default"))) // for functions in user-defined .so libraries for use with call_ext() +#endif + + +// ByondValue + +/* + Many of the routines in this library return a bool value. If true, the + operation succeeded. If false, it failed and calling Byond_LastError() will + return an error string. + + The C++ wrappers change this true/false behavior to raise exceptions instead. + This would be preferable across the board but throwing exceptions across + module boundaries is bad juju. + */ + +extern "C" { + +DUNGPUB char const *Byond_LastError(); +DUNGPUB void Byond_GetVersion(u4c *version, u4c *build); + +typedef u1c ByondValueType; +union ByondValueData { + u4c ref; + float num; + char *str; +}; + +/* + You MUST call one of the ByondValue_Init routines before using this + structure. + + You SHOULD call ByondValue_Free() to clean this structure up, but it's + only technically needed to clean up strings. For safety's sake, just be + sure to clean it up. + */ +struct CByondValue { + ByondValueType type; + u1c junk1, junk2, junk3; // padding + ByondValueData data; +}; + +DUNGPUB void ByondValue_Init(CByondValue *v); +DUNGPUB void ByondValue_InitNum(CByondValue *v, float num); +DUNGPUB bool ByondValue_InitStr(CByondValue *v, char const *str); +DUNGPUB void ByondValue_InitRef(CByondValue *v, ByondValueType type, u4c ref); +DUNGPUB void ByondValue_Free(CByondValue *v); + +DUNGPUB void ByondValue_CopyFrom(CByondValue *dst, CByondValue const *src); // frees dst's old value +DUNGPUB void ByondValue_MoveFrom(CByondValue *dst, CByondValue *src); // frees src after copy, and frees dst's old value + +DUNGPUB ByondValueType ByondValue_Type(CByondValue const *v); +DUNGPUB bool ByondValue_IsNull(CByondValue const *v); +DUNGPUB bool ByondValue_IsNum(CByondValue const *v); +DUNGPUB bool ByondValue_IsStr(CByondValue const *v); +DUNGPUB bool ByondValue_IsList(CByondValue const *v); + +DUNGPUB float ByondValue_GetNum(CByondValue const *v); +DUNGPUB char const *ByondValue_GetStr(CByondValue const *v); +DUNGPUB u4c ByondValue_GetRef(CByondValue const *v); + +DUNGPUB void ByondValue_SetNum(CByondValue *v, float f); +DUNGPUB bool ByondValue_SetStr(CByondValue *v, char const *str); +DUNGPUB void ByondValue_SetRef(CByondValue *v, ByondValueType type, u4c ref); + +DUNGPUB bool ByondValue_Equals(CByondValue const *a, CByondValue const *b); + +/* + You MUST call one of the ByondValueList_Init routines before using this + structure, and you MUST call ByoundValueList_Free() to free it. + + Routines will return false if allocation fails. + */ +struct CByondValueList { + CByondValue *items; + u4c count, capacity; +}; + +DUNGPUB void ByondValueList_Init(CByondValueList *list); +DUNGPUB bool ByondValueList_InitCount(CByondValueList *list, u4c count); +DUNGPUB void ByondValueList_Free(CByondValueList *list); + +DUNGPUB bool ByondValueList_CopyFrom(CByondValueList *dst, CByondValueList const *src); +DUNGPUB void ByondValueList_MoveFrom(CByondValueList *dst, CByondValueList *src); + +DUNGPUB bool ByondValueList_SetCount(CByondValueList *list, u4c count); // will grow capacity if needed, preferring 25% increase +DUNGPUB bool ByondValueList_SetCapacity(CByondValueList *list, u4c capacity); +DUNGPUB bool ByondValueList_Add(CByondValueList *list, CByondValue const *v); +DUNGPUB bool ByondValueList_InsertAt(CByondValueList *list, int idx, CByondValue const *v); // idx < 0 means end of list +DUNGPUB bool ByondValueList_Splice(CByondValueList *list, int idx, u4c delete_count, CByondValue const *v=0, u4c insert_count=0); // idx < 0 means end of list +DUNGPUB u4c ByondValueList_RemoveAt(CByondValueList *list, u4c idx, u4c n=1); // returns # of removed items + +// Other useful structs + +struct CByondXYZ { + s2c x, y, z, junk; +}; + +/* + In the following functions, anything that fills a result value (e.g., + ReadVar, CallProc) will create a temporary reference to the value. So if + the result is an object or list or such, it will remain valid until the + end of the current tick unless something explicitly deletes it. You can + also let go of the temporary reference early by calling Byond_DecRef(). + + If the validity of a reference is ever in doubt, call Byond_TestRef(). + + + Thread safety: + + Anything that requires reading will block if called outside of the main + thread. Write operations on the wrong thread will not block, but they will + schedule for later, return immediately, and not report failure. + */ + +DUNGPUB u4c Byond_GetStrId(char const *str); // does not add a string to the tree if not found; returns NONE if no string match + +DUNGPUB bool Byond_ReadVar(CByondValue const *loc, char const *varname, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_ReadVarByStrId(CByondValue const *loc, u4c varname, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_WriteVar(CByondValue const *loc, char const *varname, CByondValue const *val); +DUNGPUB bool Byond_WriteVarByStrId(CByondValue const *loc, u4c varname, CByondValue const *val); + +DUNGPUB bool Byond_CreateList(CByondValue *result); // result MUST be initialized first! + +DUNGPUB bool Byond_ReadList(CByondValue const *loc, CByondValueList *list); // list MUST be initialized first! +DUNGPUB bool Byond_WriteList(CByondValue const *loc, CByondValueList const *list); + +DUNGPUB bool Byond_ReadListIndex(CByondValue const *loc, CByondValue const *idx, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_WriteListIndex(CByondValue const *loc, CByondValue const *idx, CByondValue const *val); + +DUNGPUB bool Byond_ReadPointer(CByondValue const *ptr, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_WritePointer(CByondValue const *ptr, CByondValue const *val); + +/* + Proc calls: + + arg is an array of arguments; can be null arg_count is 0. + + The call is implicitly a waitfor=0 call; if the callee sleeps it will return + immediately and finish later. + + If called in the wrong thread, it will spawn() the proc and return null. + */ +DUNGPUB bool Byond_CallProc(CByondValue const *src, char const *name, CByondValue const *arg, u4c arg_count, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_CallProcByStrId(CByondValue const *src, u4c name, CByondValue const *arg, u4c arg_count, CByondValue *result); // result MUST be initialized first! + +DUNGPUB bool Byond_CallGlobalProc(char const *name, CByondValue const *arg, u4c arg_count, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_CallGlobalProcByStrId(u4c name, CByondValue const *arg, u4c arg_count, CByondValue *result); // result MUST be initialized first! + +// Use BYOND's internal value-to-text conversion +DUNGPUB bool Byond_ToString(CByondValue const *src, CByondValue *result); // result MUST be initialized first! + +// Other builtins +DUNGPUB bool Byond_Block(CByondXYZ const *corner1, CByondXYZ const *corner2, CByondValueList *result); // result MUST be initialized first! +DUNGPUB bool Byond_Length(CByondValue const *src, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_LocateIn(CByondValue const *type, CByondValue const *list, CByondValue *result); // result MUST be initialized first!; list may be a null pointer +DUNGPUB bool Byond_LocateXYZ(CByondXYZ const *xyz, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_New(CByondValue const *type, CByondValue const *argA, u4c argS, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_NewArglist(CByondValue const *type, CByondValue const *arglist, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_Refcount(CByondValue const *type, CByondValue *result); // result MUST be initialized first! +DUNGPUB bool Byond_XYZ(CByondValue const *src, CByondXYZ *xyz); // still returns true if the atom is off-map, but xyz will be 0,0,0 + +/* + Generally you don't want to mess with inc/decref calls, except that for + temporary references you can use Byond_DecRef() to let go of the temporary + reference. + + Call ByondValue_IncRef() to create a permanent reference to an object + within Byondapi. It will exist until ByondValue_DecRef() removes it or the + object is hard-deleted. + + ByondValue_DecRef() will remove a permanent reference created by Byondapi. + If there is no permanent reference, it will remove any temporary + reference that was set to expire when the tick ends. If Byondapi has no + references to the object, the call will be ignored. + + These only apply to ref types, not null/num/string. Any runtime errors + caused by decref (if the object is deleted or another object ends up + getting deleted as an indirect result) are ignored. + */ +DUNGPUB void ByondValue_IncRef(CByondValue const *src); +DUNGPUB void ByondValue_DecRef(CByondValue const *src); + +// Returns true if the ref is valid. +// Returns false if the ref was not valid and had to be changed to null. +// This only applies to ref types, not null/num/string which are always valid. +DUNGPUB bool Byond_TestRef(CByondValue *src); + +}; // extern "C" + + + +#endif // BYONDAPI_H diff --git a/crates/byondapi-sys/src/lib.rs b/crates/byondapi-sys/src/lib.rs index 739028e..8abaf23 100644 --- a/crates/byondapi-sys/src/lib.rs +++ b/crates/byondapi-sys/src/lib.rs @@ -18,6 +18,8 @@ compile_error!("BYOND API only supports Windows and Linux"); // Include byondapi-c bindings (generated by build.rs) #[allow(dead_code)] mod byond_rawbind { + #[cfg(feature = "byond-515-1617")] + include!(concat!(env!("OUT_DIR"), "/bindings_515_1617.rs")); #[cfg(feature = "byond-515-1611")] include!(concat!(env!("OUT_DIR"), "/bindings_515_1611.rs")); #[cfg(feature = "byond-515-1610")] @@ -92,7 +94,7 @@ pub use byond_rawbind::ByondValueType; pub use byond_rawbind::CByondValue; pub use byond_rawbind::CByondValueList; -#[cfg(feature = "byond-515-1611")] +#[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub use byond_rawbind::CByondXYZ; // Stabilized functions @@ -104,109 +106,106 @@ impl ByondApi { self.internal.Byond_LastError() } pub unsafe fn ByondValue_Init(&self, v: *mut CByondValue) { - self.internal.ByondValue_Init(v.cast()) + self.internal.ByondValue_Init(v) } pub unsafe fn ByondValue_InitNum(&self, v: *mut CByondValue, num: c_float) { - self.internal.ByondValue_InitNum(v.cast(), num) + self.internal.ByondValue_InitNum(v, num) } pub unsafe fn ByondValue_InitStr(&self, v: *mut CByondValue, str_: *const c_char) -> bool { - self.internal.ByondValue_InitStr(v.cast(), str_) + self.internal.ByondValue_InitStr(v, str_) } pub unsafe fn ByondValue_InitRef(&self, v: *mut CByondValue, type_: ByondValueType, ref_: u4c) { - self.internal.ByondValue_InitRef(v.cast(), type_, ref_) + self.internal.ByondValue_InitRef(v, type_, ref_) } pub unsafe fn ByondValue_Free(&self, v: *mut CByondValue) { - self.internal.ByondValue_Free(v.cast()) + self.internal.ByondValue_Free(v) } pub unsafe fn ByondValue_CopyFrom(&self, dst: *mut CByondValue, src: *const CByondValue) { - self.internal.ByondValue_CopyFrom(dst.cast(), src.cast()) + self.internal.ByondValue_CopyFrom(dst, src) } pub unsafe fn ByondValue_MoveFrom(&self, dst: *mut CByondValue, src: *mut CByondValue) { - self.internal.ByondValue_MoveFrom(dst.cast(), src.cast()) + self.internal.ByondValue_MoveFrom(dst, src) } pub unsafe fn ByondValue_Type(&self, v: *const CByondValue) -> ByondValueType { - self.internal.ByondValue_Type(v.cast()) + self.internal.ByondValue_Type(v) } pub unsafe fn ByondValue_IsNull(&self, v: *const CByondValue) -> bool { - self.internal.ByondValue_IsNull(v.cast()) + self.internal.ByondValue_IsNull(v) } pub unsafe fn ByondValue_IsNum(&self, v: *const CByondValue) -> bool { - self.internal.ByondValue_IsNum(v.cast()) + self.internal.ByondValue_IsNum(v) } pub unsafe fn ByondValue_IsStr(&self, v: *const CByondValue) -> bool { - self.internal.ByondValue_IsStr(v.cast()) + self.internal.ByondValue_IsStr(v) } pub unsafe fn ByondValue_IsList(&self, v: *const CByondValue) -> bool { - self.internal.ByondValue_IsList(v.cast()) + self.internal.ByondValue_IsList(v) } pub unsafe fn ByondValue_GetNum(&self, v: *const CByondValue) -> f32 { - self.internal.ByondValue_GetNum(v.cast()) + self.internal.ByondValue_GetNum(v) } pub unsafe fn ByondValue_GetStr(&self, v: *const CByondValue) -> *const ::std::os::raw::c_char { - self.internal.ByondValue_GetStr(v.cast()) + self.internal.ByondValue_GetStr(v) } pub unsafe fn ByondValue_GetRef(&self, v: *const CByondValue) -> u4c { - self.internal.ByondValue_GetRef(v.cast()) + self.internal.ByondValue_GetRef(v) } pub unsafe fn ByondValue_SetNum(&self, v: *mut CByondValue, f: f32) { - self.internal.ByondValue_SetNum(v.cast(), f) + self.internal.ByondValue_SetNum(v, f) } pub unsafe fn ByondValue_SetStr( &self, v: *mut CByondValue, str_: *const ::std::os::raw::c_char, ) -> bool { - self.internal.ByondValue_SetStr(v.cast(), str_) + self.internal.ByondValue_SetStr(v, str_) } pub unsafe fn ByondValue_SetRef(&self, v: *mut CByondValue, type_: ByondValueType, ref_: u4c) { - self.internal.ByondValue_SetRef(v.cast(), type_, ref_) + self.internal.ByondValue_SetRef(v, type_, ref_) } pub unsafe fn ByondValue_Equals(&self, a: *const CByondValue, b: *const CByondValue) -> bool { - self.internal.ByondValue_Equals(a.cast(), b.cast()) + self.internal.ByondValue_Equals(a, b) } pub unsafe fn ByondValueList_Init(&self, list: *mut CByondValueList) { - self.internal.ByondValueList_Init(list.cast()) + self.internal.ByondValueList_Init(list) } pub unsafe fn ByondValueList_InitCount(&self, list: *mut CByondValueList, count: u4c) -> bool { - self.internal.ByondValueList_InitCount(list.cast(), count) + self.internal.ByondValueList_InitCount(list, count) } pub unsafe fn ByondValueList_Free(&self, list: *mut CByondValueList) { - self.internal.ByondValueList_Free(list.cast()) + self.internal.ByondValueList_Free(list) } pub unsafe fn ByondValueList_CopyFrom( &self, dst: *mut CByondValueList, src: *const CByondValueList, ) -> bool { - self.internal - .ByondValueList_CopyFrom(dst.cast(), src.cast()) + self.internal.ByondValueList_CopyFrom(dst, src) } pub unsafe fn ByondValueList_MoveFrom( &self, dst: *mut CByondValueList, src: *mut CByondValueList, ) { - self.internal - .ByondValueList_MoveFrom(dst.cast(), src.cast()) + self.internal.ByondValueList_MoveFrom(dst, src) } pub unsafe fn ByondValueList_SetCount(&self, list: *mut CByondValueList, count: u4c) -> bool { - self.internal.ByondValueList_SetCount(list.cast(), count) + self.internal.ByondValueList_SetCount(list, count) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn ByondValueList_SetCapacity( &self, list: *mut CByondValueList, capacity: u4c, ) -> bool { - self.internal - .ByondValueList_SetCapacity(list.cast(), capacity) + self.internal.ByondValueList_SetCapacity(list, capacity) } pub unsafe fn ByondValueList_Add( &self, list: *mut CByondValueList, v: *const CByondValue, ) -> bool { - self.internal.ByondValueList_Add(list.cast(), v.cast()) + self.internal.ByondValueList_Add(list, v) } pub unsafe fn ByondValueList_InsertAt( &self, @@ -214,8 +213,7 @@ impl ByondApi { idx: ::std::os::raw::c_int, v: *const CByondValue, ) -> bool { - self.internal - .ByondValueList_InsertAt(list.cast(), idx, v.cast()) + self.internal.ByondValueList_InsertAt(list, idx, v) } pub unsafe fn ByondValueList_Splice( &self, @@ -226,7 +224,7 @@ impl ByondApi { insert_count: u4c, ) -> bool { self.internal - .ByondValueList_Splice(list.cast(), idx, delete_count, v.cast(), insert_count) + .ByondValueList_Splice(list, idx, delete_count, v, insert_count) } pub unsafe fn ByondValueList_RemoveAt( &self, @@ -234,7 +232,7 @@ impl ByondApi { idx: u4c, n: u4c, ) -> u4c { - self.internal.ByondValueList_RemoveAt(list.cast(), idx, n) + self.internal.ByondValueList_RemoveAt(list, idx, n) } pub unsafe fn Byond_GetStrId(&self, str_: *const ::std::os::raw::c_char) -> u4c { self.internal.Byond_GetStrId(str_) @@ -245,8 +243,7 @@ impl ByondApi { varname: *const ::std::os::raw::c_char, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_ReadVar(loc.cast(), varname, result.cast()) + self.internal.Byond_ReadVar(loc, varname, result) } pub unsafe fn Byond_ReadVarByStrId( &self, @@ -254,8 +251,7 @@ impl ByondApi { varname: u4c, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_ReadVarByStrId(loc.cast(), varname, result.cast()) + self.internal.Byond_ReadVarByStrId(loc, varname, result) } pub unsafe fn Byond_WriteVar( &self, @@ -263,8 +259,7 @@ impl ByondApi { varname: *const ::std::os::raw::c_char, val: *const CByondValue, ) -> bool { - self.internal - .Byond_WriteVar(loc.cast(), varname, val.cast()) + self.internal.Byond_WriteVar(loc, varname, val) } pub unsafe fn Byond_WriteVarByStrId( &self, @@ -272,25 +267,24 @@ impl ByondApi { varname: u4c, val: *const CByondValue, ) -> bool { - self.internal - .Byond_WriteVarByStrId(loc.cast(), varname, val.cast()) + self.internal.Byond_WriteVarByStrId(loc, varname, val) } pub unsafe fn Byond_CreateList(&self, result: *mut CByondValue) -> bool { - self.internal.Byond_CreateList(result.cast()) + self.internal.Byond_CreateList(result) } pub unsafe fn Byond_ReadList( &self, loc: *const CByondValue, list: *mut CByondValueList, ) -> bool { - self.internal.Byond_ReadList(loc.cast(), list.cast()) + self.internal.Byond_ReadList(loc, list) } pub unsafe fn Byond_WriteList( &self, loc: *const CByondValue, list: *const CByondValueList, ) -> bool { - self.internal.Byond_WriteList(loc.cast(), list.cast()) + self.internal.Byond_WriteList(loc, list) } pub unsafe fn Byond_ReadListIndex( &self, @@ -298,8 +292,7 @@ impl ByondApi { idx: *const CByondValue, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_ReadListIndex(loc.cast(), idx.cast(), result.cast()) + self.internal.Byond_ReadListIndex(loc, idx, result) } pub unsafe fn Byond_WriteListIndex( &self, @@ -307,22 +300,21 @@ impl ByondApi { idx: *const CByondValue, val: *const CByondValue, ) -> bool { - self.internal - .Byond_WriteListIndex(loc.cast(), idx.cast(), val.cast()) + self.internal.Byond_WriteListIndex(loc, idx, val) } pub unsafe fn Byond_ReadPointer( &self, ptr: *const CByondValue, result: *mut CByondValue, ) -> bool { - self.internal.Byond_ReadPointer(ptr.cast(), result.cast()) + self.internal.Byond_ReadPointer(ptr, result) } pub unsafe fn Byond_WritePointer( &self, ptr: *const CByondValue, val: *const CByondValue, ) -> bool { - self.internal.Byond_WritePointer(ptr.cast(), val.cast()) + self.internal.Byond_WritePointer(ptr, val) } pub unsafe fn Byond_CallProc( &self, @@ -333,7 +325,7 @@ impl ByondApi { result: *mut CByondValue, ) -> bool { self.internal - .Byond_CallProc(src.cast(), name, arg.cast(), arg_count, result.cast()) + .Byond_CallProc(src, name, arg, arg_count, result) } pub unsafe fn Byond_CallProcByStrId( &self, @@ -344,41 +336,65 @@ impl ByondApi { result: *mut CByondValue, ) -> bool { self.internal - .Byond_CallProcByStrId(src.cast(), name, arg.cast(), arg_count, result.cast()) + .Byond_CallProcByStrId(src, name, arg, arg_count, result) + } + #[cfg(feature = "byond-515-1617")] + pub unsafe fn Byond_CallGlobalProc( + &self, + name: *const ::std::os::raw::c_char, + arg: *const CByondValue, + arg_count: u4c, + result: *mut CByondValue, + ) -> bool { + self.internal + .Byond_CallGlobalProc(name, arg, arg_count, result) } - #[cfg(any(feature = "byond-515-1610", feature = "byond-515-1611"))] + #[cfg(feature = "byond-515-1617")] + pub unsafe fn Byond_CallGlobalProcByStrId( + &self, + name: u4c, + arg: *const CByondValue, + arg_count: u4c, + result: *mut CByondValue, + ) -> bool { + self.internal + .Byond_CallGlobalProcByStrId(name, arg, arg_count, result) + } + #[cfg(any( + feature = "byond-515-1610", + feature = "byond-515-1611", + feature = "byond-515-1617" + ))] pub unsafe fn Byond_ToString(&self, src: *const CByondValue, result: *mut CByondValue) -> bool { - self.internal.Byond_ToString(src.cast(), result.cast()) + self.internal.Byond_ToString(src, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_Block( &self, corner1: *const CByondXYZ, corner2: *const CByondXYZ, result: *mut CByondValueList, ) -> bool { - self.internal - .Byond_Block(corner1.cast(), corner2.cast(), result.cast()) + self.internal.Byond_Block(corner1, corner2, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_Length(&self, src: *const CByondValue, result: *mut CByondValue) -> bool { - self.internal.Byond_Length(src.cast(), result.cast()) + self.internal.Byond_Length(src, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_LocateIn( &self, type_: *const CByondValue, list: *const CByondValue, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_LocateIn(type_.cast(), list.cast(), result.cast()) + self.internal.Byond_LocateIn(type_, list, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_LocateXYZ(&self, xyz: *const CByondXYZ, result: *mut CByondValue) -> bool { - self.internal.Byond_LocateXYZ(xyz.cast(), result.cast()) + self.internal.Byond_LocateXYZ(xyz, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_New( &self, type_: *const CByondValue, @@ -386,38 +402,36 @@ impl ByondApi { argS: u4c, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_New(type_.cast(), argA.cast(), argS, result.cast()) + self.internal.Byond_New(type_, argA, argS, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_NewArglist( &self, type_: *const CByondValue, arglist: *const CByondValue, result: *mut CByondValue, ) -> bool { - self.internal - .Byond_NewArglist(type_.cast(), arglist.cast(), result.cast()) + self.internal.Byond_NewArglist(type_, arglist, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_Refcount( &self, type_: *const CByondValue, result: *mut CByondValue, ) -> bool { - self.internal.Byond_Refcount(type_.cast(), result.cast()) + self.internal.Byond_Refcount(type_, result) } - #[cfg(feature = "byond-515-1611")] + #[cfg(any(feature = "byond-515-1611", feature = "byond-515-1617"))] pub unsafe fn Byond_XYZ(&self, src: *const CByondValue, xyz: *mut CByondXYZ) -> bool { - self.internal.Byond_XYZ(src.cast(), xyz.cast()) + self.internal.Byond_XYZ(src, xyz) } pub unsafe fn ByondValue_IncRef(&self, src: *const CByondValue) { - self.internal.ByondValue_IncRef(src.cast()) + self.internal.ByondValue_IncRef(src) } pub unsafe fn ByondValue_DecRef(&self, src: *const CByondValue) { - self.internal.ByondValue_DecRef(src.cast()) + self.internal.ByondValue_DecRef(src) } pub unsafe fn Byond_TestRef(&self, src: *mut CByondValue) -> bool { - self.internal.Byond_TestRef(src.cast()) + self.internal.Byond_TestRef(src) } }