From: Hiroyuki_Katsura <hiroyuki.katsura.0513(a)gmail.com>
---
generator/rust.ml | 142 +++++++++++++++++++++-------
rust/tests/050_handle_properties.rs | 61 ++++++++++++
rust/tests/070_opt_args.rs | 36 +++++++
rust/tests/080_version.rs | 29 ++++++
4 files changed, 236 insertions(+), 32 deletions(-)
create mode 100644 rust/tests/050_handle_properties.rs
create mode 100644 rust/tests/070_opt_args.rs
create mode 100644 rust/tests/080_version.rs
diff --git a/generator/rust.ml b/generator/rust.ml
index 79e16dfc6..4766357be 100644
--- a/generator/rust.ml
+++ b/generator/rust.ml
@@ -64,7 +64,7 @@ use std::convert;
use std::ffi;
use std::slice;
use std::ptr;
-use std::os::raw::{c_char, c_int};
+use std::os::raw::{c_char, c_int, c_void};
#[allow(non_camel_case_types)]
@@ -79,6 +79,11 @@ extern \"C\" {
fn guestfs_last_errno(g: *mut guestfs_h) -> c_int;
}
+extern \"C\" {
+ fn free(buf: *const c_void);
+}
+
+
const GUESTFS_CREATE_NO_ENVIRONMENT: i64 = 1;
const GUESTFS_CREATE_NO_CLOSE_ON_EXIT: i64 = 2;
@@ -158,7 +163,38 @@ impl<T: Copy + Clone> Iterator for NullTerminatedIter<T>
{
}
}
-fn arg_string_list (v: &Vec<String>) -> Vec<*const i8> {
+#[repr(C)]
+struct RawList<T> {
+ size: u32,
+ ptr: *const T,
+}
+
+struct RawListIter<'a, T> {
+ current: u32,
+ list: &'a RawList<T>
+}
+
+impl<T> RawList<T> {
+ fn iter<'a>(&'a self) -> RawListIter<'a, T> {
+ RawListIter{ current: 0, list: self }
+ }
+}
+
+impl<'a, T> Iterator for RawListIter<'a, T> {
+ type Item = *const T;
+ fn next(&mut self) -> Option<*const T> {
+ if self.current >= self.list.size {
+ None
+ } else {
+ let elem = unsafe { self.list.ptr.offset(self.current as isize) };
+ self.current += 1;
+ Some(elem)
+ }
+ }
+}
+
+
+fn arg_string_list (v: &Vec<&str>) -> Vec<*const i8> {
let length = v.len();
let mut w = Vec::new();
for x in v.iter() {
@@ -185,9 +221,9 @@ fn hashmap (l: *const *const c_char) ->
collections::HashMap<String, String> {
map
}
-fn struct_list<T, S: convert::From<*const T>>(l: *const *const T) ->
Vec<S> {
+fn struct_list<T, S: convert::From<*const T>>(l: *const RawList<T>)
-> Vec<S> {
let mut v = Vec::new();
- for x in NullTerminatedIter::new(l) {
+ for x in unsafe {&*l}.iter() {
v.push(S::from(x));
}
v
@@ -202,6 +238,10 @@ fn string_list (l: *const *const c_char) -> Vec<String> {
v
}
+fn free_string_list(l: *const *const c_char) {
+ // TODO
+}
+
#[derive(Debug)]
pub struct Error {
operation: &'static str,
@@ -248,6 +288,7 @@ impl UUID {
self.uuid
}
}
+
";
List.iter (
fun { s_camel_name = name; s_name = c_name; s_cols = cols } ->
@@ -315,16 +356,34 @@ impl UUID {
pr "}\n"
) external_structs;
+ (* generate free functionf of structs *)
+ pr "\n";
+ pr "extern \"C\" {\n";
+ List.iter (
+ fun { s_camel_name = name; s_name = c_name; } ->
+ pr "fn guestfs_free_%s(v: *const Raw%s);\n" c_name name;
+ pr "fn guestfs_free_%s_list(l: *const RawList<Raw%s>);\n" c_name
name;
+ ) external_structs;
+ pr "}\n";
+
+
(* generate structs for optional arguments *)
List.iter (
fun ({ name = name; shortdesc = shortdesc;
style = (ret, args, optargs) }) ->
let cname = snake2caml name in
+ let rec contains_ptr args = match args with
+ | [] -> false
+ | OString _ ::_
+ | OStringList _::_ -> true
+ | _::xs -> contains_ptr xs
+ in
+ let opt_life_parameter = if contains_ptr optargs then "<'a>"
else "" in
if optargs <> [] then (
pr "\n";
pr "/* Optional Structs */\n";
pr "#[derive(Default)]\n";
- pr "pub struct OptArgs%s {\n" cname;
+ pr "pub struct OptArgs%s%s {\n" cname opt_life_parameter;
List.iter (
fun optarg ->
let n = translate_bad_symbols (name_of_optargt optarg) in
@@ -336,9 +395,9 @@ impl UUID {
| OInt64 _ ->
pr " _%s: Option<i64>,\n" n
| OString _ ->
- pr " _%s: Option<String>,\n" n
+ pr " _%s: Option<&'a str>,\n" n
| OStringList _ ->
- pr " _%s: Option<Vec<String>>,\n" n
+ pr " _%s: Option<Vec<&'a str>>,\n" n
) optargs;
pr "}\n\n";
@@ -363,8 +422,9 @@ impl UUID {
) optargs;
pr "}\n\n";
- pr "impl convert::From<OptArgs%s> for RawOptArgs%s {\n" cname
cname;
- pr " fn from(optargs: OptArgs%s) -> Self {\n" cname;
+ pr "impl%s convert::From<OptArgs%s%s> for RawOptArgs%s {\n"
+ opt_life_parameter cname opt_life_parameter cname;
+ pr " fn from(optargs: OptArgs%s%s) -> Self {\n" cname
opt_life_parameter;
pr " let mut bitmask = 0;\n";
pr " RawOptArgs%s {\n" cname;
List.iteri (
@@ -406,7 +466,7 @@ impl UUID {
pr " }\n";
pr "}\n";
- pr "impl OptArgs%s {\n" cname;
+ pr "impl%s OptArgs%s%s {\n" opt_life_parameter cname
opt_life_parameter;
List.iter (
fun optarg ->
let n = translate_bad_symbols (name_of_optargt optarg) in
@@ -419,11 +479,11 @@ impl UUID {
| OInt64 _ ->
pr "i64"
| OString _ ->
- pr "String"
+ pr "&'a str"
| OStringList _ ->
- pr "Vec<String>"
+ pr "Vec<&'a str>"
);
- pr ") -> OptArgs%s {\n" cname;
+ pr ") -> OptArgs%s%s {\n" cname opt_life_parameter;
pr " OptArgs%s { _%s: Some(%s), ..self }\n" cname n n;
pr " }\n"
) optargs;
@@ -471,7 +531,7 @@ impl UUID {
pr "*const Raw%s" n
| RStructList (_, n) ->
let n = camel_name_of_struct n in
- pr "*const *const Raw%s" n
+ pr "*const RawList<Raw%s>" n
);
pr ";\n";
@@ -498,9 +558,9 @@ impl UUID {
| Bool n -> pr "%s: bool" n
| Int n -> pr "%s: i32" n
| Int64 n -> pr "%s: i64" n
- | String (_, n) -> pr "%s: String" n
- | OptString n -> pr "%s: Option<String>" n
- | StringList (_, n) -> pr "%s: Vec<String>" n
+ | String (_, n) -> pr "%s: &str" n
+ | OptString n -> pr "%s: Option<&str>" n
+ | StringList (_, n) -> pr "%s: Vec<&str>" n
| BufferIn n -> pr "%s: Vec<u8>" n
| Pointer (_, n) -> pr "%s: usize" n
) args;
@@ -616,32 +676,50 @@ impl UUID {
| RConstString _ ->
pr "unsafe{ ffi::CStr::from_ptr(r) }.to_str().unwrap()\n"
| RString _ ->
- (* TODO: free r *)
- pr "unsafe { ffi::CStr::from_ptr(r) }.to_str().unwrap().to_string()"
+ pr "{";
+ pr " let s = unsafe {ffi::CStr::from_ptr(r)}\n";
+ pr " .to_str().unwrap().to_string();\n";
+ pr " unsafe { free(r as * const c_void) };\n";
+ pr " s\n";
+ pr "}\n";
| RConstOptString _ ->
- (* TODO: free ? not? *)
indent 3; pr "if r.is_null() {\n";
indent 3; pr " None\n";
indent 3; pr "} else {\n";
indent 3; pr " Some(unsafe { ffi::CStr::from_ptr(r)
}.to_str().unwrap())\n";
indent 3; pr "}";
| RStringList _ ->
- (* TODO: free r *)
- pr "string_list(r)"
+ pr "{\n";
+ pr " let s = string_list(r);\n";
+ pr " free_string_list(r);\n";
+ pr " s\n";
+ pr "}\n";
| RStruct (_, n) ->
- (* TODO: free r *)
- let n = camel_name_of_struct n in
- pr "%s::from(r)" n
+ let sn = camel_name_of_struct n in
+ pr "{\n";
+ pr " let s = %s::from(r);\n" sn;
+ pr " unsafe { guestfs_free_%s(r) };\n" n;
+ pr " s\n";
+ pr "}\n";
| RStructList (_, n) ->
- (* TODO: free r *)
- let n = camel_name_of_struct n in
- pr "struct_list::<Raw%s, %s>(r)" n n
+ let sn = camel_name_of_struct n in
+ pr "{\n";
+ pr " let l = struct_list::<Raw%s, %s>(r);\n" sn sn;
+ pr " unsafe { guestfs_free_%s_list(r) };" n;
+ pr " l\n";
+ pr "}\n";
| RHashtable _ ->
- (* TODO: free r *)
- pr "hashmap(r)"
+ pr "{\n";
+ pr " let h = hashmap(r);\n";
+ pr " free_string_list(r);\n";
+ pr " h\n";
+ pr "}\n";
| RBufferOut _ ->
- (* TODO: free r *)
- pr "unsafe { slice::from_raw_parts(r, size) }.to_vec()"
+ pr "{\n";
+ pr " let s = unsafe { slice::from_raw_parts(r, size)
}.to_vec();\n";
+ pr " unsafe { free(r as * const c_void) } ;\n";
+ pr " s\n";
+ pr "}\n";
);
pr ")\n";
pr " }\n\n"
diff --git a/rust/tests/050_handle_properties.rs b/rust/tests/050_handle_properties.rs
new file mode 100644
index 000000000..3c7b449f9
--- /dev/null
+++ b/rust/tests/050_handle_properties.rs
@@ -0,0 +1,61 @@
+/* libguestfs Python bindings
+ Copyright (C) 2009-2019 Red Hat Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern crate guestfs;
+
+use std::default::Default;
+
+#[test]
+fn verbose() {
+ let g = guestfs::Handle::create().expect("create");
+ g.set_verbose(true).expect("set_verbose");
+ assert_eq!(g.get_verbose().expect("get_verbose"), true);
+ g.set_verbose(false).expect("set_verbose");
+ assert_eq!(g.get_verbose().expect("get_verbose"), false);
+}
+
+#[test]
+fn trace() {
+ let g = guestfs::Handle::create().expect("create");
+ g.set_trace(true).expect("set_trace");
+ assert_eq!(g.get_trace().expect("get_trace"), true);
+ g.set_trace(false).expect("set_trace");
+ assert_eq!(g.get_trace().expect("get_trace"), false);
+}
+
+#[test]
+fn autosync() {
+ let g = guestfs::Handle::create().expect("create");
+ g.set_autosync(true).expect("set_autosync");
+ assert_eq!(g.get_autosync().expect("get_autosync"), true);
+ g.set_autosync(false).expect("set_autosync");
+ assert_eq!(g.get_autosync().expect("get_autosync"), false);
+}
+
+#[test]
+fn path() {
+ let g = guestfs::Handle::create().expect("create");
+ g.set_path(Some(".")).expect("set_path");
+ assert_eq!(g.get_path().expect("get_path"), ".");
+}
+
+#[test]
+fn add_drive() {
+ let g = guestfs::Handle::create().expect("create");
+ g.add_drive("/dev/null",
Default::default()).expect("add_drive");
+}
diff --git a/rust/tests/070_opt_args.rs b/rust/tests/070_opt_args.rs
new file mode 100644
index 000000000..241c95b35
--- /dev/null
+++ b/rust/tests/070_opt_args.rs
@@ -0,0 +1,36 @@
+/* libguestfs Python bindings
+ Copyright (C) 2009-2019 Red Hat Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern crate guestfs;
+
+use std::default::Default;
+
+#[test]
+fn no_optargs() {
+ let g = guestfs::Handle::create().expect("create");
+ g.add_drive("/dev/null", Default::default())
+ .expect("add_drive");
+}
+
+#[test]
+fn one_optarg() {
+ let g = guestfs::Handle::create().expect("create");
+ g.add_drive("/dev/null",
+ guestfs::OptArgsAddDrive::default().readonly(true))
+ .expect("add_drive");
+}
diff --git a/rust/tests/080_version.rs b/rust/tests/080_version.rs
new file mode 100644
index 000000000..ab5314edc
--- /dev/null
+++ b/rust/tests/080_version.rs
@@ -0,0 +1,29 @@
+/* libguestfs Python bindings
+ Copyright (C) 2009-2019 Red Hat Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern crate guestfs;
+
+use std::default::Default;
+
+#[test]
+fn version() {
+ let g = guestfs::Handle::create().expect("create");
+ let v = g.version().expect("version");
+ assert_eq!(v.major, 1)
+}
+
--
2.20.1 (Apple Git-117)