virtualbox_rs 0.4.2

A Rust library for interacting with VirtualBox, providing a safe and idiomatic interface to the VirtualBox API.
Documentation
use crate::VboxError;
use vbox_raw::sys_lib::{nsID, IEvent};

pub(crate) fn cast_event<T>(object: *mut IEvent, iid_str: &[u8; 37]) -> Result<*mut T, VboxError> {
    let mut result: *mut std::os::raw::c_void = std::ptr::null_mut();
    let iid = create_ns_id_from_str(iid_str);
    let iid_ptr = &iid as *const nsID;
    let lp_vtbl = unsafe { (*(object)).lpVtbl };

    let get_fn_ptr =
        unsafe { (*lp_vtbl).QueryInterface }.ok_or(VboxError::get_fn_error("QueryInterface"))?;
    let result_code = unsafe { get_fn_ptr(object, iid_ptr, &mut result) };
    if result_code != 0 {
        return Err(VboxError::new(
            result_code,
            "QueryInterface",
            "".to_string(),
            None,
        ));
    }
    let new_obj: *mut T = result.cast();
    Ok(new_obj)
}

pub fn create_ns_id_from_str(id_str: &[u8; 37]) -> nsID {
    let id = std::str::from_utf8(id_str).unwrap();
    let id_vec: Vec<&str> = id.split("-").collect();
    let m0 = str_to_u32(id_vec.get(0).unwrap_or(&""));
    let m1 = str_to_u16(id_vec.get(1).unwrap_or(&""));
    let m2 = str_to_u16(id_vec.get(2).unwrap_or(&""));
    let k = format!(
        "{}{}",
        id_vec.get(3).unwrap_or(&""),
        id_vec.get(4).unwrap_or(&"")
    );
    let chunks: Vec<String> = k
        .split_whitespace()
        .flat_map(|word| {
            word.chars()
                .collect::<Vec<char>>()
                .chunks(2)
                .map(|chunk| chunk.iter().collect::<String>())
                .collect::<Vec<_>>()
        })
        .collect();
    let chunks: Vec<u8> = chunks
        .to_vec()
        .iter()
        .map(|a| str_to_u8(a.as_str()))
        .collect();
    let (first, _) = chunks.split_at(8);
    let mut m3 = [0u8; 8];
    m3.copy_from_slice(first);
    let iid = nsID { m0, m1, m2, m3 };
    iid
}

fn str_to_u32(s: &str) -> u32 {
    u32::from_str_radix(&s, 16).unwrap_or(0)
}
fn str_to_u16(s: &str) -> u16 {
    u16::from_str_radix(&s, 16).unwrap_or(0)
}
fn str_to_u8(s: &str) -> u8 {
    u8::from_str_radix(&s, 16).unwrap_or(0)
}