1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//! Helpers for managing call()s from BYOND code.
use std::ffi::{CString, CStr, NulError};
use std::slice;
use std::sync::Mutex;
//use libc;

// Yes this will totally break if multithreading would happen, but it won't so hooray!
// Can't use an on-stack value to give back to BYOND for obvious reasons.
lazy_static! {
    static ref BYOND_RETURN: Mutex<CString> = {
        Mutex::new(CString::new("hi!".as_bytes()).unwrap())
    };
}


/// Returns a pointer that can be returned to BYOND from a `call()()`ed function,
/// to return a string.
pub fn return_to_byond(string: &str) -> Result<*const i8, NulError> {
    let cstr = CString::new(string.as_bytes())?;

    let mut mutex = BYOND_RETURN.lock().unwrap();

    *mutex = cstr;
    Ok(mutex.as_ptr())
}


/// Turns the arguments supplied by BYOND into a more workable vector.
///
/// All strings are converted into UTF-8 losilly. You've been warned.
pub fn from_byond_args(n: i32, v: *const *const i8) -> Vec<String> {
    let mut args = Vec::new();
    unsafe {
        let slice = slice::from_raw_parts(v, n as usize);
        for ptr in slice {
            let cstr = CStr::from_ptr(*ptr);
            let string = String::from_utf8_lossy(cstr.to_bytes()).into_owned();
            args.push(string);
        }
    }
    args
}