[Libguestfs] [PATCH 1/2] Rust bindings: Add Event structs, Clarify Handle lifetime

Hiroyuki Katsura hiroyuki.katsura.0513 at gmail.com
Mon Aug 5 06:59:31 UTC 2019


Without clarifying handle's lifetime, it is unable
to see how long the callbacks which the handle
owns will live. Then, Rust compiler will infer
that the callbacks have 'static lifetime. It is
not convenient for users.
---
 generator/rust.ml                 | 38 ++++++++++++++++++++++++++++++-
 rust/src/base.rs                  | 23 +++++++++++++------
 rust/src/error.rs                 |  2 +-
 rust/src/event.rs                 |  4 ++++
 rust/src/lib.rs                   |  2 ++
 rust/tests/040_create_multiple.rs |  2 +-
 6 files changed, 61 insertions(+), 10 deletions(-)
 create mode 100644 rust/src/event.rs

diff --git a/generator/rust.ml b/generator/rust.ml
index a1735602c..1f5cefa62 100644
--- a/generator/rust.ml
+++ b/generator/rust.ml
@@ -72,6 +72,42 @@ extern \"C\" {
 }
 ";
 
+  (* event enum *)
+  pr "\n";
+  pr "pub enum Event {\n";
+  List.iter (
+    fun (name, _) ->
+      pr "    %s,\n" (snake2caml name)
+  ) events;
+  pr "}\n\n";
+
+  pr "impl Event {\n";
+  pr "    pub fn to_u64(&self) -> u64 {\n";
+  pr "        match self {\n";
+  List.iter (
+    fun (name, i) ->
+      pr "            Event::%s => %d,\n" (snake2caml name) i
+  ) events;
+  pr "        }\n";
+  pr "    }\n";
+  pr "    pub fn from_bitmask(bitmask: u64) -> Option<Event> {\n";
+  pr "        match bitmask {\n";
+  List.iter (
+    fun (name, i) ->
+      pr "            %d => Some(Event::%s),\n" i (snake2caml name)
+  ) events;
+  pr "            _ => None,\n";
+  pr "        }\n";
+  pr "    }\n";
+  pr "}\n\n";
+
+  pr "pub const EVENT_ALL: [Event; %d] = [\n" (List.length events);
+  List.iter (
+    fun (name, _) ->
+      pr "    Event::%s,\n" (snake2caml name)
+  ) events;
+  pr "];\n";
+
   List.iter (
     fun { s_camel_name = name; s_name = c_name; s_cols = cols } ->
       pr "\n";
@@ -356,7 +392,7 @@ extern \"C\" {
   pr "}\n";
 
 
-  pr "impl Handle {\n";
+  pr "impl<'a> Handle<'a> {\n";
   List.iter (
     fun ({ name = name; shortdesc = shortdesc; longdesc = longdesc;
           style = (ret, args, optargs) } as f) ->
diff --git a/rust/src/base.rs b/rust/src/base.rs
index 02ad33535..c17607cb3 100644
--- a/rust/src/base.rs
+++ b/rust/src/base.rs
@@ -17,6 +17,9 @@
  */
 
 use crate::error;
+use crate::event;
+use crate::guestfs;
+use std::collections;
 
 #[allow(non_camel_case_types)]
 #[repr(C)]
@@ -34,31 +37,37 @@ extern "C" {
 const GUESTFS_CREATE_NO_ENVIRONMENT: i64 = 1;
 const GUESTFS_CREATE_NO_CLOSE_ON_EXIT: i64 = 2;
 
-pub struct Handle {
+pub struct Handle<'a> {
     pub(crate) g: *mut guestfs_h,
+    pub(crate) callbacks: collections::HashMap<
+        event::EventHandle,
+        Box<Box<dyn Fn(guestfs::Event, event::EventHandle, &[u8], &[u64]) + 'a>>,
+    >,
 }
 
-impl Handle {
-    pub fn create() -> Result<Handle, error::Error> {
+impl<'a> Handle<'a> {
+    pub fn create() -> Result<Handle<'a>, error::Error> {
         let g = unsafe { guestfs_create() };
         if g.is_null() {
             Err(error::Error::Create)
         } else {
-            Ok(Handle { g })
+            let callbacks = collections::HashMap::new();
+            Ok(Handle { g, callbacks })
         }
     }
 
-    pub fn create_flags(flags: CreateFlags) -> Result<Handle, error::Error> {
+    pub fn create_flags(flags: CreateFlags) -> Result<Handle<'a>, error::Error> {
         let g = unsafe { guestfs_create_flags(flags.to_libc_int()) };
         if g.is_null() {
             Err(error::Error::Create)
         } else {
-            Ok(Handle { g })
+            let callbacks = collections::HashMap::new();
+            Ok(Handle { g, callbacks })
         }
     }
 }
 
-impl Drop for Handle {
+impl<'a> Drop for Handle<'a> {
     fn drop(&mut self) {
         unsafe { guestfs_close(self.g) }
     }
diff --git a/rust/src/error.rs b/rust/src/error.rs
index 705ee1735..e526121e8 100644
--- a/rust/src/error.rs
+++ b/rust/src/error.rs
@@ -56,7 +56,7 @@ impl convert::From<str::Utf8Error> for Error {
     }
 }
 
-impl base::Handle {
+impl<'a> base::Handle<'a> {
     pub(crate) fn get_error_from_handle(&self, operation: &'static str) -> Error {
         let c_msg = unsafe { guestfs_last_error(self.g) };
         let message = unsafe { utils::char_ptr_to_string(c_msg).unwrap() };
diff --git a/rust/src/event.rs b/rust/src/event.rs
new file mode 100644
index 000000000..c363e913a
--- /dev/null
+++ b/rust/src/event.rs
@@ -0,0 +1,4 @@
+#[derive(Hash, PartialEq, Eq)]
+pub struct EventHandle {
+    eh: i32,
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index cc41a99f8..81adef2a3 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -18,9 +18,11 @@
 
 mod base;
 mod error;
+mod event;
 mod guestfs;
 mod utils;
 
 pub use crate::base::*;
 pub use crate::error::*;
+pub use crate::event::*;
 pub use crate::guestfs::*;
diff --git a/rust/tests/040_create_multiple.rs b/rust/tests/040_create_multiple.rs
index cc93554a3..970c988af 100644
--- a/rust/tests/040_create_multiple.rs
+++ b/rust/tests/040_create_multiple.rs
@@ -18,7 +18,7 @@
 
 extern crate guestfs;
 
-fn create() -> guestfs::Handle {
+fn create<'a>() -> guestfs::Handle<'a> {
     match guestfs::Handle::create() {
         Ok(g) => g,
         Err(e) => panic!("fail: {:?}", e),
-- 
2.20.1 (Apple Git-117)




More information about the Libguestfs mailing list