use crate::api::params::{
CommonInitParams, DriverInitParams, KVMInitParams, MemflowConnectorParams, MemflowInitParams,
};
use std::convert::TryFrom;
use std::ffi::{CStr, IntoStringError};
use std::os::raw::c_char;
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CommonInitParamsFFI {
pub vm_name: *mut c_char,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub enum KVMInitParamsFFI {
UnixSocket { path: *mut c_char },
}
#[repr(C)]
#[derive(Debug, Clone)]
pub enum MemflowConnectorParamsFFI {
Default {
args_arr: *mut *mut c_char,
args_arr_len: usize,
},
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct MemflowInitParamsFFI {
pub connector_name: *mut c_char,
pub connector_args: MemflowConnectorParamsFFI,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct DriverInitParamsFFI {
pub common: CommonInitParamsFFI,
pub kvm: KVMInitParamsFFI,
pub memflow: MemflowInitParamsFFI,
}
impl TryFrom<DriverInitParamsFFI> for DriverInitParams {
type Error = IntoStringError;
fn try_from(value: DriverInitParamsFFI) -> Result<Self, Self::Error> {
let vm_name = if value.common.vm_name.is_null() {
None
} else {
Some(
unsafe { CStr::from_ptr(value.common.vm_name) }
.to_owned()
.into_string()?,
)
};
let common = vm_name.map(|v| CommonInitParams { vm_name: v });
let kvm_socket = match value.kvm {
KVMInitParamsFFI::UnixSocket { path } => {
if path.is_null() {
None
} else {
Some(unsafe { CStr::from_ptr(path) }.to_owned().into_string()?)
}
}
};
let kvm = kvm_socket.map(|v| KVMInitParams::UnixSocket { path: v });
let MemflowInitParamsFFI {
connector_name,
connector_args,
} = value.memflow;
let memflow = if connector_name.is_null() {
None
} else {
let args = match connector_args {
MemflowConnectorParamsFFI::Default {
args_arr,
args_arr_len,
} => {
if !args_arr.is_null() && args_arr_len > 0 {
let args = unsafe { std::slice::from_raw_parts(args_arr, args_arr_len) };
let mut args_vec = Vec::with_capacity(args.len());
for s in args.iter() {
args_vec.push(unsafe { CStr::from_ptr(*s) }.to_owned().into_string()?);
}
Some(MemflowConnectorParams::Default { args: args_vec })
} else {
Some(MemflowConnectorParams::Default { args: vec![] })
}
}
};
Some(MemflowInitParams {
connector_name: unsafe { CStr::from_ptr(connector_name) }
.to_owned()
.into_string()?,
connector_args: args,
})
};
Ok(DriverInitParams {
common,
kvm,
memflow,
..Default::default()
})
}
}