lava 0.4.9

Rust wrapper to manipulate Vulkan more conveniently than with bindings.
Documentation
use std::ffi::CString;
use std::ffi::CStr;
use std::cmp;
use std::mem;
use std::os::raw::c_char;
use utils::c_bindings::*;
use utils::vk_traits::*;
use utils::vk_ptr::*;
use vulkan::vk::*;

pub fn vk_to_raw_value<W : VkWrappedType<R>, R>(value: &W) -> R {
    unsafe {
        let mut dst = mem::MaybeUninit::uninit().assume_init();
        W::vk_to_raw(value, &mut dst);
        dst
    }
}

pub fn vk_to_raw_value_checked<W : VkWrappedType<R>, R : Default>(value: &Option<W>) -> R {
    match value {
        Some(v) => vk_to_raw_value(v),
        None => Default::default()
    }
}

pub fn vk_to_raw_array<W : VkWrappedType<R>, R>(array: &[W], dst: &mut[R]) {
    let len = cmp::min(array.len(), dst.len());

    for i in 0..len {
        W::vk_to_raw(&array[i], &mut dst[i])
    }
}

pub fn vk_to_wrapped_array<W, R : VkRawType<W>>(array: &[R], dst: &mut[W]) {
    let len = cmp::min(array.len(), dst.len());

    for i in 0..len {
        dst[i] = R::vk_to_wrapped(&array[i])
    }
}

pub fn fill_vk_array<T : Default>(dst: &mut[T]) {
    for i in 0..dst.len() {
        dst[i] = T::default();
    }
}

pub fn to_array<T : Copy>(src: &[T], dst: &mut[T]) {
    let len = cmp::min(src.len(), dst.len());

    for i in 0..len {
        dst[i] = src[i];
    }
}

pub fn string_to_byte_array(string: &str, dst: &mut[c_char]) {
    let bytes = string.as_bytes();
    let len = cmp::min(bytes.len(), dst.len() - 1);

    for i in 0..len {
        dst[i] = bytes[i] as c_char;
    }

    dst[len] = 0;
}

pub fn new_vk_array<R : VkRawType<W>, W>(length: u32, ptr: *const R) -> Vec<W> {
    unsafe {
        let len = length as usize;
        let mut vector : Vec<W> = Vec::with_capacity(len);

        for i in 0..len {
            vector.push(R::vk_to_wrapped(&*ptr.add(i)));
        }

        vector
    }
}

pub fn new_vk_array_checked<R : VkRawType<W>, W>(length: u32, ptr: *const R) -> Option<Vec<W>> {
    if ptr.is_null() {
        None
    } else {
        Some(new_vk_array(length, ptr))
    }
}

pub fn new_vk_value<R : VkRawType<W>, W>(ptr: *const R) -> W {
    unsafe {
        R::vk_to_wrapped(&*ptr)
    }
}

pub fn new_vk_value_checked<R : VkRawType<W>, W>(ptr: *const R) -> Option<W> {
    unsafe {
        if ptr.is_null() {
            None
        } else {
            Some(R::vk_to_wrapped(&*ptr))
        }
    }
}

pub fn new_array<T : Copy>(length: u32, ptr: *const T) -> Vec<T> {
    unsafe {
        let len = length as usize;
        let mut vector : Vec<T> = Vec::with_capacity(len);

        for i in 0..len {
            vector.push(*ptr.add(i));
        }

        vector
    }
}

pub fn new_string(ptr: *const c_char) -> String {
    unsafe {
        // TODO: remove condition?
        if ptr.is_null() {
            String::from("")
        } else {
            String::from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes().to_vec())
        }
    }
}

pub fn new_string_checked(ptr: *const c_char) -> Option<String> {
    if ptr.is_null() {
        Some(new_string(ptr))
    } else {
        None
    }
}

pub fn new_string_vec(length: u32, ptr: *const *const c_char) -> Vec<String> {
    let len = length as usize;
    let mut result : Vec<String> = Vec::with_capacity(len);

    for i in 0..len {
        result.push(new_string(unsafe { *ptr.add(i) }));
    }

    result
}

pub fn new_string_ref<'a>(ptr: *const c_char) -> &'a str {
    unsafe {
        if ptr.is_null() {
                ""
        } else {
            let len = std::ffi::CStr::from_ptr(ptr).to_bytes().len();
            let slice = std::slice::from_raw_parts(ptr as *const u8, len);

            std::str::from_utf8_unchecked(slice)
        }
    }
}

pub fn new_string_ref_checked<'a>(ptr: *const c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(new_string_ref(ptr))
    }
}

pub fn new_string_ref_vec<'a>(length: u32, ptr: *const *const c_char) -> Vec<&'a str> {
    let len = length as usize;
    let mut result : Vec<&'a str> = Vec::with_capacity(len);

    for i in 0..len {
        result.push(new_string_ref(unsafe { *ptr.add(i) }));
    }

    result
}

pub fn vec_from_ptr<T>(length: usize, ptr: *const T) -> Vec<T> {
    unsafe {
        Vec::from_raw_parts(mem::transmute(ptr), length, length)
    }
}

pub fn vec_from_ptr_checked<T>(length: usize, ptr: *const T) -> Option<Vec<T>> {
    if ptr.is_null() {
        None
    } else {
        Some(vec_from_ptr(length, ptr))
    }
}

pub fn slice_from_ptr<'a, T>(length: usize, ptr: *const T) -> &'a [T] {
    unsafe {
        std::slice::from_raw_parts(ptr, length)
    }
}

pub unsafe fn get_vk_instance_function_pointer(instance: RawVkInstance, name: &str) -> *const c_void {
    let c_string = CString::new(name).unwrap();

    vkGetInstanceProcAddr(instance, c_string.as_c_str().as_ptr())
}

pub unsafe fn get_vk_device_function_pointer(device: RawVkDevice, name: &str) -> *const c_void {
    let c_string = CString::new(name).unwrap();

    vkGetDeviceProcAddr(device, c_string.as_c_str().as_ptr())
}

extern {
    fn vkGetInstanceProcAddr(instance: RawVkInstance, name: *const c_char) -> *const c_void;
    fn vkGetDeviceProcAddr(device: RawVkDevice, name: *const c_char) -> *const c_void;
}