* added virStreamEventAddCallback function
* added new types: StreamEventCallback and FreeCallback
* added new field: callback for storing event callback
* drop: will drop the Box<callback> if any
* added wrapper event_callback for easier callback authoring for the
user (so that closures with Fn or FnMut references could be used)
* added padding function event_free to just makes it compile (Rust
should not need this, because Rust sticks to RAII)
Signed-off-by: Zixing Liu <liushuyu(a)aosc.io>
---
src/stream.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/stream.rs b/src/stream.rs
index 96e37cb..3a83b34 100644
--- a/src/stream.rs
+++ b/src/stream.rs
@@ -50,6 +50,12 @@ extern "C" {
fn virStreamFree(c: sys::virStreamPtr) -> libc::c_int;
fn virStreamAbort(c: sys::virStreamPtr) -> libc::c_int;
fn virStreamFinish(c: sys::virStreamPtr) -> libc::c_int;
+ fn virStreamEventAddCallback(c: sys::virStreamPtr,
+ event: libc::c_int,
+ callback: StreamEventCallback,
+ opaque: *const libc::c_void,
+ ff: FreeCallback)
+ -> libc::c_int;
fn virStreamEventUpdateCallback(c: sys::virStreamPtr,
events: libc::c_int) -> libc::c_int;
fn virStreamEventRemoveCallback(c: sys::virStreamPtr) -> libc::c_int;
@@ -64,9 +70,26 @@ pub const VIR_STREAM_EVENT_HANGUP: StreamEventType = (1 << 3);
pub type StreamFlags = self::libc::c_uint;
pub const VIR_STREAM_NONBLOCK: StreamFlags = (1 << 0);
-#[derive(Debug)]
+pub type StreamEventCallback = extern "C" fn(sys::virStreamPtr, libc::c_int,
*const libc::c_void);
+pub type FreeCallback = extern "C" fn(*mut libc::c_void);
+
+// wrapper for callbacks
+extern "C" fn event_callback(c: sys::virStreamPtr, flags: libc::c_int, opaque:
*const libc::c_void) {
+ let flags = flags as StreamFlags;
+ let shadow_self = unsafe {
+ &mut*(opaque as *mut Stream)
+ };
+ if let Some(callback) = &mut shadow_self.callback {
+ callback(&Stream::from_ptr(c), flags);
+ }
+}
+
+extern "C" fn event_free(_opaque: *mut libc::c_void) {}
+
+// #[derive(Debug)]
pub struct Stream {
ptr: Option<sys::virStreamPtr>,
+ callback: Option<Box<dyn FnMut(&Stream, StreamEventType)>>,
}
impl Drop for Stream {
@@ -79,6 +102,13 @@ impl Drop for Stream {
)
}
}
+ if self.callback.is_some() {
+ if let Err(e) = self.event_remove_callback() {
+ panic!("Unable to remove event callback for Stream, code {},
message: {}",
+ e.code,
+ e.message)
+ }
+ }
}
}
@@ -94,7 +124,7 @@ impl Stream {
}
pub fn from_ptr(ptr: sys::virStreamPtr) -> Stream {
- Stream { ptr: Some(ptr) }
+ Stream { ptr: Some(ptr), callback: None }
}
pub fn as_ptr(&self) -> sys::virStreamPtr {
@@ -151,6 +181,18 @@ impl Stream {
usize::try_from(ret).map_err(|_| Error::new())
}
+ pub fn event_add_callback<F: 'static + FnMut(&Stream,
StreamEventType)>(&mut self, events: StreamEventType, cb: F) -> Result<(),
Error> {
+ let ret = unsafe {
+ let ptr = &*self as *const _ as *const _;
+ virStreamEventAddCallback(self.as_ptr(), events as libc::c_int,
event_callback, ptr, event_free)
+ };
+ if ret == -1 {
+ return Err(Error::new());
+ }
+ self.callback = Some(Box::new(cb));
+ return Ok(());
+ }
+
pub fn event_update_callback(&self, events: StreamEventType) -> Result<(),
Error> {
let ret = unsafe {
virStreamEventUpdateCallback(self.as_ptr(), events as libc::c_int)
--
2.25.0