[libvirt] [PATCH Rust 2/4] libvirt-rust: stream: add more functions in stream

Zixing Liu posted 4 patches 5 years ago
There is a newer version of this series
[libvirt] [PATCH Rust 2/4] libvirt-rust: stream: add more functions in stream
Posted by Zixing Liu 5 years ago
* 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@aosc.io>
---
 src/stream.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/stream.rs b/src/stream.rs
index de272ab..1ffd186 100644
--- a/src/stream.rs
+++ b/src/stream.rs
@@ -47,6 +47,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;
@@ -61,9 +67,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 {
@@ -75,6 +98,13 @@ impl Drop for Stream {
                        e.message)
             }
         }
+        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)
+            }
+        }
     }
 }
 
@@ -90,7 +120,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 {
@@ -147,6 +177,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.24.0


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list