@@ -72,4 +72,3 @@ include ui/test/Makefile.am
include man/Makefile.am
include utils/Makefile.am
-
@@ -450,6 +450,15 @@ esac
AC_DEFINE_UNQUOTED(TFTP_TYPE, $tftp_type, [tftp client type])
+AC_ARG_VAR(
+ [CARGO_OPTS],
+ [Arguments to cargo]
+)
+AC_ARG_VAR(
+ [RUSTC_TARGET_NAME],
+ [Target as passed to cargo]
+)
+
default_cflags="--std=gnu99 -g \
-Wall -W -Wunused -Wstrict-prototypes -Wmissing-prototypes \
-Wmissing-declarations -Wredundant-decls"
@@ -12,6 +12,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+include lib/rust/Makefile.am
+
core_lib = lib/libpbcore.la
noinst_LTLIBRARIES += $(core_lib)
@@ -70,7 +72,12 @@ lib_libpbcore_la_SOURCES = \
lib/efi/efivar.h \
lib/efi/efivar.c \
lib/param_list/param_list.c \
- lib/param_list/param_list.h
+ lib/param_list/param_list.h \
+ lib/rust/rustlibs.c \
+ lib/rust/rustlibs.c
+
+lib_libpbcore_la_LIBADD = \
+ $(rust_lib)
if ENABLE_MTD
lib_libpbcore_la_SOURCES += \
new file mode 100644
@@ -0,0 +1,117 @@
+[[package]]
+name = "dtoa"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "itoa"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libtool"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num-traits"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustlibs"
+version = "0.1.0"
+dependencies = [
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libtool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.12.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
+"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
+"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
+"checksum libtool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f576520ad5e2848b26568964320a4073984db2a11147ac4f9c2fc7be1f93b8d2"
+"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3"
+"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
+"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
+"checksum serde 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e928fecdb00fe608c96f83a012633383564e730962fc7a0b79225a6acf056798"
+"checksum serde_derive 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "95f666a2356d87ce4780ea15b14b13532785579a5cad2dcba5292acc75f6efe2"
+"checksum serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc848d073be32cd982380c06587ea1d433bc1a4c4a111de07ec2286a3ddade8"
+"checksum serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57781ed845b8e742fc2bf306aba8e3b408fe8c366b900e3769fbc39f49eb8b39"
+"checksum syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)" = "517f6da31bc53bf080b9a77b29fbd0ff8da2f5a2ebd24c73c2238274a94ac7cb"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
new file mode 100644
@@ -0,0 +1,20 @@
+[package]
+name = "rustlibs"
+build = "build.rs"
+version = "0.1.0"
+authors = ["Samuel Mendoza-Jonas <sam@mendozajonas.com>"]
+
+[dependencies]
+serde = "1.0"
+serde_derive = "1.0"
+serde_json = "1.0"
+libc = "0.2"
+
+[lib]
+crate-type = ["staticlib"]
+
+[build-dependencies]
+libtool = "0.1"
+
+[profile.release]
+lto = true
new file mode 100644
@@ -0,0 +1,30 @@
+# 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; version 2 of the License.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+rust_lib = librustlibs.la
+
+noinst_LTLIBRARIES += $(rust_lib)
+
+librustlibs_la_SOURCES = ""
+
+CARGO_TARGET_DIR := $(abs_top_builddir)/lib/rust
+
+$(rust_lib):
+ CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) cargo build --release --manifest-path $(top_srcdir)/lib/rust/Cargo.toml $(CARGO_OPTS)
+ ln -sf $(CARGO_TARGET_DIR)/$(RUSTC_TARGET_NAME)/release/librustlibs.a
+ ln -sf $(CARGO_TARGET_DIR)/$(RUSTC_TARGET_NAME)/release/librustlibs.la
+ ln -sf $(CARGO_TARGET_DIR)/$(RUSTC_TARGET_NAME)/release/.libs
+
+clean-local:
+ CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) cargo clean --manifest-path $(top_srcdir)/lib/rust/Cargo.toml
new file mode 100644
@@ -0,0 +1,70 @@
+/*
+ * From https://docs.rs/libtool/0.1.1/libtool/
+ * Upstream doesn't handle some of the directory structure we use in Petitboot,
+ * use a few extra environment variables to properly determine the target paths.
+ */
+
+use std::env;
+use std::fs::File;
+use std::fs;
+use std::io::prelude::*;
+use std::os::unix::fs::symlink;
+use std::path::PathBuf;
+
+/// Generate libtool archive file ${lib}.la
+pub fn generate_convenience_lib(lib: &str) -> std::io::Result<()> {
+ let self_version = env!("CARGO_PKG_VERSION");
+ let profile = env::var("PROFILE").unwrap();
+ let target_arch = env::var("TARGET").unwrap();
+ let target_dir_env = env::var("CARGO_TARGET_DIR").unwrap();
+
+ /* Check if the output directory will include the arch */
+ let target_dir = if PathBuf::from(format!("{}/{}",
+ target_dir_env, target_arch)).exists() {
+ format!("{}/{}/{}", target_dir_env, target_arch, profile)
+ } else {
+ format!("{}/{}", target_dir_env, profile)
+ };
+
+ /* Location of original static library */
+ let old_lib_path = PathBuf::from(format!("{}/{}.a",
+ target_dir, lib));
+ /* Paths for new .la file and symlinks */
+ let libs_dir = format!("{}/.libs", target_dir);
+ let libs_path = PathBuf::from(&libs_dir);
+ let la_path = PathBuf::from(format!("{}/{}.la",
+ target_dir, lib));
+ let new_lib_path = PathBuf::from(format!("{}/{}.a", libs_dir, lib));
+
+ match fs::create_dir_all(&libs_path) {
+ Ok(()) => println!("libs_path created"),
+ _ => panic!("Failed to create libs_path"),
+ }
+
+ if la_path.exists() {
+ fs::remove_file(&la_path)?;
+ }
+
+ /* PathBuf.exists() traverses symlinks so just try and remove it */
+ match fs::remove_file(&new_lib_path) {
+ Ok(_v) => {},
+ Err(e) => println!("Error removing symlink: {:?}", e),
+ }
+
+ let mut file = File::create(&la_path)?;
+ writeln!(file, "# {}.la - a libtool library file", lib)?;
+ writeln!(file, "# Generated by libtool-rust {}", self_version)?;
+ writeln!(file, "dlname=''")?;
+ writeln!(file, "library_names=''")?;
+ writeln!(file, "old_library='{}.a'", lib)?;
+ writeln!(file, "inherited_linker_flags=' -pthread -lm -ldl'")?;
+ writeln!(file, "installed=no")?;
+ writeln!(file, "shouldnotlink=no")?;
+
+ symlink(&old_lib_path, &new_lib_path)?;
+ Ok(())
+}
+
+fn main() {
+ generate_convenience_lib("librustlibs").unwrap();
+}
new file mode 100644
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 IBM Corporation
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ */
+
+#include <log/log.h>
+#include <talloc/talloc.h>
+
+#include "rustlibs.h"
+
+enum field_type {
+ FIELD_STR,
+ FIELD_I64,
+ FIELD_F64,
+};
+
+/* Internal FFI Structs */
+struct ArgumentRaw {
+ char *name;
+ enum field_type type;
+ int64_t arg_i64;
+ double arg_f64;
+ char *arg_str;
+};
+
+struct CommandRaw {
+ char *platform;
+ char *name;
+ char *cmd;
+ char *args_fmt;
+ struct ArgumentRaw *args;
+ size_t n_args;
+ char *help;
+};
+
+struct CommandArray {
+ struct CommandRaw *commands;
+ size_t len;
+};
+
+/* Provided by librustlibs */
+struct CommandArray *parse_json(const char *filename);
+void free_command_array(struct CommandArray *commands);
+
+int parse_command_file(void *ctx, const char *path, struct command **commands)
+{
+ struct CommandArray *raw_commands;
+ struct CommandRaw *tmp;
+ struct command *new;
+ struct argument *arg;
+ unsigned int i, j, len;
+
+ raw_commands = parse_json(path);
+ if (!raw_commands) {
+ pb_log("Failed to parse machine command\n");
+ return 0;
+ }
+
+ len = raw_commands->len;
+ new = talloc_zero_array(ctx, struct command, len);
+ for (i = 0; i < len; i++) {
+ tmp = &raw_commands->commands[i];
+ new[i].platform = talloc_strdup(new, tmp->platform);
+ new[i].name = talloc_strdup(new, tmp->name);
+ new[i].cmd = talloc_strdup(new, tmp->cmd);
+ new[i].args_fmt = talloc_strdup(new, tmp->args_fmt);
+
+ new[i].n_args = tmp->n_args;
+ new[i].args = talloc_zero_array(new, struct argument,
+ new[i].n_args);
+ for (j = 0; j < tmp->n_args; j++) {
+ arg = &new[i].args[j];
+ arg->name = talloc_strdup(new, tmp->args[j].name);
+ arg->type = tmp->args[j].type;
+ switch (tmp->args[j].type) {
+ case FIELD_STR:
+ arg->arg_str = talloc_strdup(new,
+ tmp->args[j].arg_str);
+ break;
+ case FIELD_I64:
+ arg->arg_i64 = tmp->args[j].arg_i64;
+ break;
+ case FIELD_F64:
+ arg->arg_f64 = tmp->args[j].arg_f64;
+ break;
+ default:
+ pb_log_fn("Unknown field type %d for arg '%s'\n",
+ tmp->args[j].type, tmp->args[j].name);
+ break;
+ }
+ }
+
+ new[i].help = talloc_strdup(new, tmp->help);
+ }
+
+ free_command_array(raw_commands);
+
+ *commands = new;
+ return len;
+}
new file mode 100644
@@ -0,0 +1,11 @@
+#ifndef __RUST_LIBS__
+#define __RUST_LIBS__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <types/types.h>
+
+int parse_command_file(void *ctx, const char *path, struct command **commands);
+
+#endif /* __RUST_LIBS__ */
new file mode 100644
@@ -0,0 +1,230 @@
+#[macro_use]
+extern crate serde_derive;
+
+extern crate serde;
+extern crate serde_json;
+extern crate libc;
+
+use std::ffi::CString;
+use std::ffi::CStr;
+use std::os::raw::c_char;
+use std::fs::File;
+use std::path::Path;
+use std::ptr;
+use std::mem;
+use libc::{c_long, c_double};
+
+/* Rust representations */
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Command {
+ platform: CString,
+ name: CString,
+ cmd: CString,
+ arg_fmt: CString,
+ args: Vec<Argument>,
+ help: CString,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+enum FieldType {
+ FieldString(CString),
+ // TODO Commands which display as yes/no that hide some actual command?
+ // FieldBool(Bool),
+ FieldInt(i64),
+ FieldFloat(f64),
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Argument {
+ name: CString,
+ arg: FieldType,
+}
+
+/* FFI respresentations */
+#[repr(C)]
+pub struct CommandArray {
+ bytes: *mut CommandRaw,
+ len: usize,
+}
+
+#[repr(C)]
+pub struct CommandRaw {
+ platform: *mut c_char,
+ name: *mut c_char,
+ cmd: *mut c_char,
+ arg_fmt: *mut c_char,
+ args: *mut ArgumentRaw,
+ n_args: usize,
+ help: *mut c_char,
+}
+
+impl CommandRaw {
+ /*
+ * We need to convert several fields into FFI-suitable types and we
+ * don't want to 'partially forget' the Command structs, so we
+ * clone the various fields and forget them. The vec is then shrunk
+ * and forgotten so it can be passed as an array C will recognise.
+ */
+ fn new(command: &Command) -> CommandRaw {
+ CommandRaw {
+ platform: command.platform.clone().into_raw(),
+ name: command.name.clone().into_raw(),
+ cmd: command.cmd.clone().into_raw(),
+ arg_fmt: command.arg_fmt.clone().into_raw(),
+ args: CommandRaw::args_into_raw(&command.args),
+ n_args: command.args.len(),
+ help: command.help.clone().into_raw()
+ }
+ }
+
+ fn args_into_raw(args: &Vec<Argument>) -> *mut ArgumentRaw {
+
+ let mut args_raw = Vec::<ArgumentRaw>::new();
+
+ for arg in args {
+ let raw_arg = ArgumentRaw::new(&arg);
+ args_raw.push(raw_arg);
+ }
+
+ args_raw.shrink_to_fit();
+ let ptr = args_raw.as_mut_ptr();
+ mem::forget(args_raw);
+
+ return ptr;
+ }
+}
+
+#[repr(C)]
+/*
+ * Rust enums are not C enums and Rust doesn't have a 'union' concept like in C
+ * so we just declare all the fields here and set them based on arg_type.
+ */
+pub struct ArgumentRaw {
+ name: *mut c_char,
+ arg_type: FieldTypeRaw,
+ arg_i64: c_long,
+ arg_f64: c_double,
+ arg_str: *mut c_char,
+}
+
+impl ArgumentRaw {
+ fn new(arg: &Argument) -> ArgumentRaw {
+ let raw_arg = match arg.arg {
+ FieldType::FieldString(ref s) => {
+ ArgumentRaw {
+ name: arg.name.clone().into_raw(),
+ arg_type: FieldTypeRaw::RawString,
+ arg_i64: 0,
+ arg_f64: 0.0,
+ arg_str: s.clone().into_raw(),
+ }
+ },
+ FieldType::FieldInt(i) => {
+ ArgumentRaw {
+ name: arg.name.clone().into_raw(),
+ arg_type: FieldTypeRaw::RawInt,
+ arg_i64: i,
+ arg_f64: 0.0,
+ arg_str: ptr::null_mut(),
+ }
+ },
+ FieldType::FieldFloat(f) => {
+ ArgumentRaw {
+ name: arg.name.clone().into_raw(),
+ arg_type: FieldTypeRaw::RawFloat,
+ arg_i64: 0,
+ arg_f64: f,
+ arg_str: ptr::null_mut(),
+ }
+ },
+ };
+ return raw_arg;
+ }
+}
+
+#[repr(C)]
+#[derive(PartialEq)]
+enum FieldTypeRaw {
+ RawString = 0,
+ RawInt,
+ RawFloat,
+}
+
+/*
+ * Take a CommandArray pointer from C and reclaim the CommandRaw
+ * structs and their members/
+ * We can't avoid the unsafe {} invocations since we're reading arbitrary
+ * memory, but it's contained to this function.
+ */
+#[no_mangle]
+pub extern fn free_command_array(commands: *mut CommandArray) {
+
+ let ptr = unsafe { Box::from_raw(commands) };
+ let raw_vec = unsafe { Vec::from_raw_parts(ptr.bytes,
+ ptr.len,
+ ptr.len) };
+ for raw_command in raw_vec.iter() {
+ unsafe {
+ let _platform = CString::from_raw(raw_command.platform);
+ let _name = CString::from_raw(raw_command.name);
+ let _cmd = CString::from_raw(raw_command.cmd);
+ let _arg_fmt = CString::from_raw(raw_command.arg_fmt);
+ /* n_args */
+ let arg_vec = Vec::from_raw_parts(raw_command.args,
+ raw_command.n_args,
+ raw_command.n_args);
+ for raw_arg in arg_vec.iter() {
+ let _name = CString::from_raw(raw_arg.name);
+ if raw_arg.arg_type == FieldTypeRaw::RawString {
+ let _arg_str = CString::from_raw(raw_arg.arg_str);
+ }
+ }
+ let _help = CString::from_raw(raw_command.help);
+ }
+ }
+
+ /* Frees once it goes out of scope */
+ println!("Rust reclaimed {} command structs", raw_vec.len());
+}
+
+#[no_mangle]
+pub extern fn parse_json(filename: *const c_char) -> *mut CommandArray {
+
+ let file: String;
+ unsafe {
+ /* Can't trust the promise of a string from C */
+ file = CStr::from_ptr(filename).to_string_lossy().into_owned();
+ }
+
+ let json_path = Path::new(&file);
+ let json_file = match File::open(json_path) {
+ Err(e) => {
+ println!("Could not open file: {}", e);
+ return ptr::null_mut();
+ }
+ Ok(f) => f,
+ };
+
+ let commands: Vec<Command> = match serde_json::from_reader(json_file) {
+ Err(e) => {
+ println!("Could not parse JSON: {}", e);
+ return ptr::null_mut();
+ }
+ Ok(c) => c,
+ };
+
+ /* Convert commands into a form more easily passed to C */
+ let mut ffi_vec = Vec::<CommandRaw>::new();
+ for command in commands.iter() {
+ let raw_command = CommandRaw::new(&command);
+ ffi_vec.push(raw_command);
+ }
+
+ let len = ffi_vec.len();
+ ffi_vec.shrink_to_fit();
+ let ffi_ptr = ffi_vec.as_mut_ptr();
+ mem::forget(ffi_vec);
+
+ let wrapper = Box::new(CommandArray { bytes: ffi_ptr, len: len });
+ return Box::into_raw(wrapper);
+}
@@ -66,6 +66,32 @@ struct boot_option {
} type;
};
+enum cmd_arg_type {
+ ARG_STR,
+ ARG_I64,
+ ARG_F64,
+};
+
+struct argument {
+ char *name;
+ enum cmd_arg_type type;
+ union {
+ char *arg_str;
+ int64_t arg_i64;
+ double arg_f64;
+ };
+};
+
+struct command {
+ char *platform;
+ char *name;
+ char *cmd;
+ char *args_fmt;
+ unsigned int n_args;
+ struct argument *args;
+ char *help;
+};
+
struct plugin_option {
char *id;
char *name;
@@ -74,10 +100,14 @@ struct plugin_option {
char *version;
char *date;
char *plugin_file;
+ char *command_file;
unsigned int n_executables;
char **executables;
+ unsigned int n_commands;
+ struct command *commands;
+
void *ui_info;
};
For plugin commands the command definitions are stored in a JSON file as part of the plugin. Instead of doing even more string parsing in C the Rust library provides an interface to the popular Serde library. The Rust interface provides a few FFI-safe definitions to pass data back and forth but does all the parsing itself. The library is built statically, but some extra work is done in build.rs to help it link into the existing Autoconf more easily. This is heavily based on the libtool crate[0] with some improvements. [0] https://docs.rs/libtool/0.1.1/libtool/ Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> --- Makefile.am | 1 - configure.ac | 9 ++ lib/Makefile.am | 9 +- lib/rust/Cargo.lock | 117 ++++++++++++++++++++++ lib/rust/Cargo.toml | 20 ++++ lib/rust/Makefile.am | 30 ++++++ lib/rust/build.rs | 70 +++++++++++++ lib/rust/rustlibs.c | 109 ++++++++++++++++++++ lib/rust/rustlibs.h | 11 +++ lib/rust/src/lib.rs | 230 +++++++++++++++++++++++++++++++++++++++++++ lib/types/types.h | 30 ++++++ 11 files changed, 634 insertions(+), 2 deletions(-) create mode 100644 lib/rust/Cargo.lock create mode 100644 lib/rust/Cargo.toml create mode 100644 lib/rust/Makefile.am create mode 100644 lib/rust/build.rs create mode 100644 lib/rust/rustlibs.c create mode 100644 lib/rust/rustlibs.h create mode 100644 lib/rust/src/lib.rs