#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
use crate::{
Error, Result,
sys::{qemu_plugin_read_register, qemu_plugin_reg_descriptor, qemu_plugin_register},
};
#[cfg(all(
not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")),
feature = "num-traits"
))]
use num_traits::{FromBytes, PrimInt};
#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
use std::{
ffi::CStr,
fmt::{Debug, Formatter},
marker::PhantomData,
};
#[cfg(not(any(
feature = "plugin-api-v0",
feature = "plugin-api-v1",
feature = "plugin-api-v2",
feature = "plugin-api-v3",
feature = "plugin-api-v4"
)))]
use crate::sys::{GByteArray, qemu_plugin_write_register};
#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
#[derive(Clone)]
pub struct RegisterDescriptor<'a> {
handle: usize,
pub name: String,
pub feature: Option<String>,
marker: PhantomData<&'a ()>,
}
#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
impl<'a> From<qemu_plugin_reg_descriptor> for RegisterDescriptor<'a> {
fn from(descriptor: qemu_plugin_reg_descriptor) -> Self {
let name = unsafe { CStr::from_ptr(descriptor.name) }
.to_str()
.expect("Register name is not valid UTF-8")
.to_string();
let feature = if descriptor.feature.is_null() {
None
} else {
Some(
unsafe { CStr::from_ptr(descriptor.feature) }
.to_str()
.expect("Register feature is not valid UTF-8")
.to_string(),
)
};
Self {
handle: descriptor.handle as usize,
name,
feature,
marker: PhantomData,
}
}
}
#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
impl<'a> Debug for RegisterDescriptor<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RegisterDescriptor")
.field("name", &self.name)
.field("feature", &self.feature)
.finish()
}
}
#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
impl<'a> RegisterDescriptor<'a> {
pub fn read(&self) -> Result<Vec<u8>> {
use crate::g_byte_array_free;
let byte_array = unsafe {
use crate::g_byte_array_new;
g_byte_array_new()
};
let result = unsafe {
qemu_plugin_read_register(self.handle as *mut qemu_plugin_register, byte_array)
};
if result == -1 {
return Err(Error::RegisterReadError {
name: self.name.clone(),
});
}
let mut data = Vec::new();
data.extend_from_slice(unsafe {
std::slice::from_raw_parts((*byte_array).data, (*byte_array).len as usize)
});
assert_eq!(
unsafe { g_byte_array_free(byte_array, true) },
std::ptr::null_mut(),
"g_byte_array_free must return NULL"
);
Ok(data)
}
#[cfg(not(any(
feature = "plugin-api-v0",
feature = "plugin-api-v1",
feature = "plugin-api-v2",
feature = "plugin-api-v3",
feature = "plugin-api-v4"
)))]
pub fn write(&self, data: &mut [u8]) -> Result<()> {
let mut buf = GByteArray {
data: data.as_mut_ptr(),
len: data.len() as u32,
};
if unsafe { qemu_plugin_write_register(self.handle as *mut _, &mut buf as *mut GByteArray) }
== 0
{
Err(Error::RegisterWriteError {
name: self.name.clone(),
})
} else {
Ok(())
}
}
#[cfg(feature = "num-traits")]
pub fn read_be<T>(&self) -> Result<T>
where
T: PrimInt + FromBytes + Sized,
T: FromBytes<Bytes = [u8; std::mem::size_of::<T>()]>,
{
let data = self.read()?;
let mut bytes = [0; std::mem::size_of::<T>()];
bytes.copy_from_slice(&data);
Ok(T::from_be_bytes(&bytes))
}
#[cfg(feature = "num-traits")]
pub fn read_le<T>(&self) -> Result<T>
where
T: PrimInt + FromBytes + Sized,
T: FromBytes<Bytes = [u8; std::mem::size_of::<T>()]>,
{
let data = self.read()?;
let mut bytes = [0; std::mem::size_of::<T>()];
bytes.copy_from_slice(&data);
Ok(T::from_le_bytes(&bytes))
}
}