qemu_plugin/register/
mod.rs1#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
3use crate::{
4 Error, Result,
5 sys::{qemu_plugin_read_register, qemu_plugin_reg_descriptor, qemu_plugin_register},
6};
7#[cfg(all(
8 not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")),
9 feature = "num-traits"
10))]
11use num_traits::{FromBytes, PrimInt};
12#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
13use std::{
14 ffi::CStr,
15 fmt::{Debug, Formatter},
16 marker::PhantomData,
17};
18
19#[cfg(not(any(
20 feature = "plugin-api-v0",
21 feature = "plugin-api-v1",
22 feature = "plugin-api-v2",
23 feature = "plugin-api-v3",
24 feature = "plugin-api-v4"
25)))]
26use crate::sys::{GByteArray, qemu_plugin_write_register};
27
28#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
29#[derive(Clone)]
30pub struct RegisterDescriptor<'a> {
37 handle: usize,
40 pub name: String,
42 pub feature: Option<String>,
44 marker: PhantomData<&'a ()>,
45}
46
47#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
48impl<'a> From<qemu_plugin_reg_descriptor> for RegisterDescriptor<'a> {
49 fn from(descriptor: qemu_plugin_reg_descriptor) -> Self {
50 let name = unsafe { CStr::from_ptr(descriptor.name) }
51 .to_str()
52 .expect("Register name is not valid UTF-8")
53 .to_string();
54
55 let feature = if descriptor.feature.is_null() {
56 None
57 } else {
58 Some(
59 unsafe { CStr::from_ptr(descriptor.feature) }
60 .to_str()
61 .expect("Register feature is not valid UTF-8")
62 .to_string(),
63 )
64 };
65
66 Self {
67 handle: descriptor.handle as usize,
68 name,
69 feature,
70 marker: PhantomData,
71 }
72 }
73}
74
75#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
76impl<'a> Debug for RegisterDescriptor<'a> {
77 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78 f.debug_struct("RegisterDescriptor")
79 .field("name", &self.name)
80 .field("feature", &self.feature)
81 .finish()
82 }
83}
84
85#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
86impl<'a> RegisterDescriptor<'a> {
87 pub fn read(&self) -> Result<Vec<u8>> {
93 use crate::g_byte_array_free;
94
95 let byte_array = unsafe {
96 use crate::g_byte_array_new;
97 g_byte_array_new()
98 };
99
100 let result = unsafe {
101 qemu_plugin_read_register(self.handle as *mut qemu_plugin_register, byte_array)
102 };
103
104 if result == -1 {
105 return Err(Error::RegisterReadError {
106 name: self.name.clone(),
107 });
108 }
109
110 let mut data = Vec::new();
111 data.extend_from_slice(unsafe {
112 std::slice::from_raw_parts((*byte_array).data, (*byte_array).len as usize)
113 });
114
115 assert_eq!(
116 unsafe { g_byte_array_free(byte_array, true) },
117 std::ptr::null_mut(),
118 "g_byte_array_free must return NULL"
119 );
120
121 Ok(data)
122 }
123
124 #[cfg(not(any(
125 feature = "plugin-api-v0",
126 feature = "plugin-api-v1",
127 feature = "plugin-api-v2",
128 feature = "plugin-api-v3",
129 feature = "plugin-api-v4"
130 )))]
131 pub fn write(&self, data: &mut [u8]) -> Result<()> {
136 let mut buf = GByteArray {
137 data: data.as_mut_ptr(),
138 len: data.len() as u32,
139 };
140 if unsafe { qemu_plugin_write_register(self.handle as *mut _, &mut buf as *mut GByteArray) }
141 == 0
142 {
143 Err(Error::RegisterWriteError {
144 name: self.name.clone(),
145 })
146 } else {
147 Ok(())
148 }
149 }
150
151 #[cfg(feature = "num-traits")]
152 pub fn read_be<T>(&self) -> Result<T>
158 where
159 T: PrimInt + FromBytes + Sized,
160 T: FromBytes<Bytes = [u8; std::mem::size_of::<T>()]>,
161 {
162 let data = self.read()?;
163 let mut bytes = [0; std::mem::size_of::<T>()];
164 bytes.copy_from_slice(&data);
165 Ok(T::from_be_bytes(&bytes))
166 }
167
168 #[cfg(feature = "num-traits")]
169 pub fn read_le<T>(&self) -> Result<T>
175 where
176 T: PrimInt + FromBytes + Sized,
177 T: FromBytes<Bytes = [u8; std::mem::size_of::<T>()]>,
178 {
179 let data = self.read()?;
180 let mut bytes = [0; std::mem::size_of::<T>()];
181 bytes.copy_from_slice(&data);
182 Ok(T::from_le_bytes(&bytes))
183 }
184}