From bb0cb3e730d57b834222dfddbd7d4b6d3c0fc8c6 Mon Sep 17 00:00:00 2001 From: Hiroyuki Katsura Date: Mon, 5 Aug 2019 15:59:31 +0900 Subject: [PATCH] Rust bindings: Add Event structs, Clarify Handle lifetime 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 {\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>, + >, } -impl Handle { - pub fn create() -> Result { +impl<'a> Handle<'a> { + pub fn create() -> Result, 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 { + pub fn create_flags(flags: CreateFlags) -> Result, 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 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),