Skip to content

Commit

Permalink
Merge pull request #3 from jupyterkat/main
Browse files Browse the repository at this point in the history
Add some stuff, fixes some stuff
  • Loading branch information
tigercat2000 authored Oct 23, 2023
2 parents 1a4223d + 2971228 commit d2e3b41
Show file tree
Hide file tree
Showing 18 changed files with 702 additions and 173 deletions.
2 changes: 1 addition & 1 deletion crates/byondapi-rs-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
10 changes: 6 additions & 4 deletions crates/byondapi-rs-test/dm_project/dm_project.dme
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions crates/byondapi-rs-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/byondapi-rs-test/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::{
use tempfile::TempDir;

#[test]
#[ignore]
#[cfg(windows)]
fn test_byondapi_with_dreamdaemon() {
let dll = build_dylib();
Expand Down
5 changes: 3 additions & 2 deletions crates/byondapi-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
17 changes: 17 additions & 0 deletions crates/byondapi-rs/src/byond_string.rs
Original file line number Diff line number Diff line change
@@ -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<T: Into<Vec<u8>>>(string: T) -> Result<u4c, Error> {
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<u4c, Error> {
let res = unsafe { byond().Byond_GetStrId(string.as_ptr()) };
if res == u2c::MAX as u32 {
return Err(Error::NonExistentString);
}
Ok(res)
}
19 changes: 16 additions & 3 deletions crates/byondapi-rs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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"),
}
}
}
Expand Down
46 changes: 46 additions & 0 deletions crates/byondapi-rs/src/global_call.rs
Original file line number Diff line number Diff line change
@@ -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<T: Into<Vec<u8>>>(name: T, args: &[ByondValue]) -> Result<ByondValue, Error> {
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<ByondValue, Error> {
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)
}
15 changes: 15 additions & 0 deletions crates/byondapi-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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() -> ());
60 changes: 24 additions & 36 deletions crates/byondapi-rs/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ impl ByondValueList {
pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn into_value(&self) -> Result<ByondValue, Error> {
// 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
Expand Down Expand Up @@ -149,49 +163,35 @@ impl Default for ByondValueList {
}
}

impl TryFrom<&ByondValue> for ByondValueList {
impl TryFrom<ByondValue> for ByondValueList {
type Error = Error;

fn try_from(value: &ByondValue) -> Result<Self, Self::Error> {
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<Self, Self::Error> {
value.get_list()
}
}

impl TryFrom<&ByondValueList> for ByondValue {
impl TryFrom<&ByondValue> for ByondValueList {
type Error = Error;

fn try_from(value: &ByondValueList) -> Result<Self, Self::Error> {
// 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<Self, Self::Error> {
value.get_list()
}
}

impl TryFrom<ByondValue> for ByondValueList {
impl TryFrom<&ByondValueList> for ByondValue {
type Error = Error;

fn try_from(value: ByondValue) -> Result<Self, Self::Error> {
(&value).try_into()
fn try_from(value: &ByondValueList) -> Result<Self, Self::Error> {
value.into_value()
}
}

impl TryFrom<ByondValueList> for ByondValue {
type Error = Error;

fn try_from(value: ByondValueList) -> Result<Self, Self::Error> {
(&value).try_into()
value.into_value()
}
}

Expand All @@ -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<ByondValueList> for Vec<ByondValue> {
fn from(value: ByondValueList) -> Self {
Expand Down
10 changes: 8 additions & 2 deletions crates/byondapi-rs/src/static_global.rs
Original file line number Diff line number Diff line change
@@ -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::<super::InitFunc> {
func.0();
}
let library = {
let result = libloading::os::windows::Library::open_already_loaded("byondcore.dll");

Expand All @@ -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::<super::InitFunc> {
func.0();
}
let library = libloading::os::unix::Library::this();
match unsafe { byondapi_sys::ByondApi::init_from_library(library) } {
Err(e) => {
Expand Down
Loading

0 comments on commit d2e3b41

Please sign in to comment.