Skip to content

Commit

Permalink
Merge pull request #2 from jupyterkat/main
Browse files Browse the repository at this point in the history
iterators doesn't cause runtimes anymore, stop to_vec'ing the slices
  • Loading branch information
tigercat2000 authored Oct 4, 2023
2 parents 2e2ac99 + 56009de commit 1a4223d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 23 deletions.
6 changes: 5 additions & 1 deletion crates/byondapi-rs-test/dm_project/dm_project.dme
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
/test/proc/test_ref()
var/turf/T = locate(1,1,1)
var/ret = call_ext("byondapi_test.dll", "byond:test_ref")(T)
world.log << ret

/test/proc/test_ptr()
var/x = "meow"
Expand Down Expand Up @@ -127,6 +126,11 @@
if(ret != 7)
throw EXCEPTION("str length failed [json_encode(ret)]")

/test/proc/test_list_non_assoc()
var/list/L = list("cat", "dog", "parrot")

call_ext("byondapi_test.dll", "byond:test_non_assoc_list")(L)

/test/proc/test_list_key_lookup()
var/list/L = list("cat" = 7, "dog" = 5, "parrot" = 4)

Expand Down
37 changes: 30 additions & 7 deletions crates/byondapi-rs-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub unsafe extern "C" fn test_list_key_lookup(
argv: *mut ByondValue,
) -> ByondValue {
setup_panic_handler();
let mut args = parse_args(argc, argv);
let args = parse_args(argc, argv);

let list = args.get_mut(0).unwrap();

Expand Down Expand Up @@ -293,12 +293,7 @@ pub unsafe extern "C" fn test_list_key_lookup(
let map = list
.iter()
.unwrap()
.map(|(k, v)| {
(
k.get_string().unwrap(),
v.unwrap().get_number().unwrap() as u32,
)
})
.map(|(k, v)| (k.get_string().unwrap(), v.get_number().unwrap() as u32))
.collect::<Vec<_>>();

assert_eq!(
Expand All @@ -324,3 +319,31 @@ pub unsafe extern "C" fn test_ref(argc: byondapi_sys::u4c, argv: *mut ByondValue

ByondValue::try_from(format!("turf_id: {turf_id}, turf_type: {turf_type}")).unwrap()
}

#[no_mangle]
pub unsafe extern "C" fn test_non_assoc_list(
argc: byondapi_sys::u4c,
argv: *mut ByondValue,
) -> ByondValue {
setup_panic_handler();
let args = parse_args(argc, argv);
let list = args.get(0).unwrap();

let map = list
.iter()
.unwrap()
.map(|(k, v)| {
if !v.is_null() {
panic!("value is not null")
}
k.get_string().unwrap()
})
.collect::<Vec<_>>();

assert_eq!(
map,
vec!["cat".to_owned(), "dog".to_owned(), "parrot".to_owned()]
);

ByondValue::new()
}
7 changes: 5 additions & 2 deletions crates/byondapi-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ use crate::value::ByondValue;
/// # Safety
/// Don't pass in a null argv pointer please god
/// Just give this what BYOND gives you and pray for the best
pub unsafe fn parse_args(argc: byondapi_sys::u4c, argv: *mut ByondValue) -> Vec<ByondValue> {
unsafe { std::slice::from_raw_parts_mut(argv, argc as usize).to_vec() }
pub unsafe fn parse_args(
argc: byondapi_sys::u4c,
argv: *mut ByondValue,
) -> &'static mut [ByondValue] {
unsafe { std::slice::from_raw_parts_mut(argv, argc as usize) }
}

/// Re-export of byondapi_sys for all low level things you may run into.
Expand Down
34 changes: 21 additions & 13 deletions crates/byondapi-rs/src/value/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::ffi::CString;
use byondapi_sys::{u4c, ByondValueType, CByondValue};

use super::ByondValue;
use crate::{static_global::byond, typecheck_trait::ByondTypeCheck, Error};
use crate::{map::byond_length, static_global::byond, typecheck_trait::ByondTypeCheck, Error};

/// # Compatibility with the C++ API
impl ByondValue {
Expand Down Expand Up @@ -199,35 +199,43 @@ impl ByondValue {
self.read_var(name)?.try_into()
}

/// Iterates through the assoc values of the list if this value is a list, if the value isn't a list then the iterator will be empty.
/// 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
/// (key, value) for proper assoc lists
pub fn iter(
&self,
) -> Result<impl Iterator<Item = (ByondValue, Option<ByondValue>)> + '_, Error> {
pub fn iter(&self) -> Result<impl Iterator<Item = (ByondValue, ByondValue)> + '_, Error> {
if !self.is_list() {
return Err(Error::NotAList);
}
let len: f32 = byond_length(self)?.try_into()?;
Ok(ListIterator {
value: self,
len: len as u32,
ctr: 1,
})
}
}

struct ListIterator<'a> {
value: &'a ByondValue,
len: u32,
ctr: u32,
}
impl<'a> Iterator for ListIterator<'a> {
type Item = (ByondValue, Option<ByondValue>);
type Item = (ByondValue, ByondValue);
fn next(&mut self) -> Option<Self::Item> {
let key = self
.value
.read_list_index_internal(&ByondValue::from(self.ctr as f32))
.ok()?;
let value = self.value.read_list_index_internal(&key).ok();
self.ctr += 1;
return Some((key, value));
if self.ctr <= self.len {
let key = self
.value
.read_list_index_internal(&ByondValue::from(self.ctr as f32))
.ok()?;
let value = self.value.read_list_index_internal(&key).ok()?;
self.ctr += 1;
Some((key, value))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.len as usize))
}
}

0 comments on commit 1a4223d

Please sign in to comment.