fui-rs 0.2.3-alpha2

Retained-mode Rust UI SDK for EffinDOM
Documentation
use crate::event;

pub fn host_service_result_buffer_ptr() -> *mut u8 {
    event::__fui_text_buffer() as *mut u8
}

pub fn host_service_result_buffer_size() -> u32 {
    event::__fui_text_buffer_size()
}

fn assert_result_byte_length(result_len: u32, import_name: &str) {
    let capacity = host_service_result_buffer_size();
    if result_len > capacity {
        panic!(
            "Host service {} returned {} bytes but the shared result buffer only holds {}.",
            import_name, result_len, capacity
        );
    }
}

pub fn decode_host_service_string_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> String {
    assert_result_byte_length(result_len, import_name);
    if result_len == 0 {
        return String::new();
    }
    let bytes = unsafe { std::slice::from_raw_parts(result_ptr as *const u8, result_len as usize) };
    String::from_utf8_lossy(bytes).into_owned()
}

pub fn decode_host_service_bytes_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<u8> {
    assert_result_byte_length(result_len, import_name);
    if result_len == 0 {
        return Vec::new();
    }
    unsafe { std::slice::from_raw_parts(result_ptr as *const u8, result_len as usize) }.to_vec()
}

pub fn decode_host_service_i32_array_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<i32> {
    assert_result_byte_length(result_len, import_name);
    assert_eq!(
        result_len & 3,
        0,
        "Host service {} returned misaligned i32 array byte length.",
        import_name
    );
    if result_len == 0 {
        return Vec::new();
    }
    unsafe {
        std::slice::from_raw_parts(result_ptr as *const i32, (result_len >> 2) as usize).to_vec()
    }
}

pub fn decode_host_service_u32_array_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<u32> {
    assert_result_byte_length(result_len, import_name);
    assert_eq!(
        result_len & 3,
        0,
        "Host service {} returned misaligned u32 array byte length.",
        import_name
    );
    if result_len == 0 {
        return Vec::new();
    }
    unsafe {
        std::slice::from_raw_parts(result_ptr as *const u32, (result_len >> 2) as usize).to_vec()
    }
}

pub fn decode_host_service_i64_array_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<i64> {
    assert_result_byte_length(result_len, import_name);
    assert_eq!(
        result_len & 7,
        0,
        "Host service {} returned misaligned i64 array byte length.",
        import_name
    );
    if result_len == 0 {
        return Vec::new();
    }
    unsafe {
        std::slice::from_raw_parts(result_ptr as *const i64, (result_len >> 3) as usize).to_vec()
    }
}

pub fn decode_host_service_u64_array_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<u64> {
    assert_result_byte_length(result_len, import_name);
    assert_eq!(
        result_len & 7,
        0,
        "Host service {} returned misaligned u64 array byte length.",
        import_name
    );
    if result_len == 0 {
        return Vec::new();
    }
    unsafe {
        std::slice::from_raw_parts(result_ptr as *const u64, (result_len >> 3) as usize).to_vec()
    }
}

pub fn decode_host_service_f64_array_result(
    result_ptr: *mut u8,
    result_len: u32,
    import_name: &str,
) -> Vec<f64> {
    assert_result_byte_length(result_len, import_name);
    assert_eq!(
        result_len & 7,
        0,
        "Host service {} returned misaligned f64 array byte length.",
        import_name
    );
    if result_len == 0 {
        return Vec::new();
    }
    unsafe {
        std::slice::from_raw_parts(result_ptr as *const f64, (result_len >> 3) as usize).to_vec()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn decodes_string_result_from_shared_text_buffer() {
        let ptr = host_service_result_buffer_ptr();
        let bytes = b"demo-host";
        unsafe {
            std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len());
        }
        assert_eq!(
            decode_host_service_string_result(ptr, bytes.len() as u32, "demo_service"),
            "demo-host"
        );
    }
}