diff --git a/bindings/const_generator.py b/bindings/const_generator.py
index 5f8d6a24f813ec4575c7323416aa98d0b472e5d3..db69d55a9b71bca5d118810d09d190233e917c65 100644
--- a/bindings/const_generator.py
+++ b/bindings/const_generator.py
@@ -32,7 +32,7 @@ template = {
             ]
         },
     'rust': {
-            'header': "// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.rs]\nextern crate libc;\n\n",
+            'header': "#![allow(non_camel_case_types)]\n// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.rs]\nuse libc;\n",
             'footer': "",
             # prefixes for constant filenames of all archs - case sensitive
             'arm.h': 'keystone',
@@ -47,65 +47,59 @@ template = {
             'keystone.h': 'keystone',
             'comment_open': '/*',
             'comment_close': '*/',
-            'out_file': './rust/src/%s_const.rs',
+            'out_file': './rust/keystone-sys/src/%s_const.rs',
             'rules': [
                 {
-                    'regex': r'(API|ARCH)_.*',
+                    'regex': r'(API)_.*',
                     'pre': '\n',
-                    'line_format': 'pub const KS_{0} : u32 = {1};\n',
+                    'line_format': 'pub const {0}: u32 = {1};\n',
                     'fn': (lambda x: x),
-                    'post': '\n',
                 },
                 {   'regex': r'MODE_.*',
-                    'pre': 'bitflags! {{\n\tpub flags Mode : u32 {{\n',
-                    'line_format': '\t\tconst {0} = {1},\n',
-                    'fn': (lambda x: x),
-                    'post': '\t}\n}\n',
+                    'pre': '\n' +
+                            'bitflags! {{\n' +
+                            '#[repr(C)]\n' +
+                            '    pub struct Mode: u32 {{\n',
+                    'line_format': '        const {0} = {1};\n',
+                    'fn': (lambda x: '_'.join(x.split('_')[1:]) if not re.match(r'MODE_\d+', x) else x),
+                    'post': '    }\n}',
                 },
                 {
                     'regex': r'ARCH_.*',
-                    'pre': '#[derive(Debug, PartialEq, Clone, Copy)]\n' + 
+                    'pre': '\n' +
+                            '#[repr(C)]\n' +
+                            '#[derive(Debug, PartialEq, Clone, Copy)]\n' +
                             'pub enum Arch {{\n',
-                    'line_format': '\t{0},\n',
-                    'fn': (lambda x: '_'.join(x.split('_')[1:])),
-                    'post': '}\n\n',
-                },
-                {   'regex': r'ARCH_.*',
-                    'pre': 'impl Arch {{\n\t#[inline]\n\tpub fn val(&self) -> u32 {{\n\t\tmatch *self {{\n',
-                    'line_format': '\t\t\tArch::{0} => {1},\n',
+                    'line_format': '    {0} = {1},\n',
                     'fn': (lambda x: '_'.join(x.split('_')[1:])),
-                    'post': '\t\t}\n\t}\n}\n',
+                    'post': '}\n',
                 },
                 {
-                    'regex': r'OPT_([A-Z]+)$',
-                    'pre': '#[derive(Debug, PartialEq, Clone, Copy)]\n' + 
+                    'regex': r'(OPT_([A-Z]+)|OPT_SYM_RESOLVER)$',
+                    'pre': '#[repr(C)]\n' +
+                            '#[derive(Debug, PartialEq, Clone, Copy)]\n' +
                             'pub enum OptionType {{\n',
-                    'line_format': '\t{0},\n',
-                    'fn': (lambda x: '_'.join(x.split('_')[1:])),
-                    'post': '\tMAX,\n' +
-                            '}\n',
-                },
-                {   
-                    'regex': r'OPT_([A-Z]+)$',
-                    'pre': 'impl OptionType {{\n\t#[inline]\n\tpub fn val(&self) -> u32 {{\n\t\tmatch *self {{\n',
-                    'line_format': '\t\t\tOptionType::{0} => {1},\n',
+                    'line_format': '    {0} = {1},\n',
                     'fn': (lambda x: '_'.join(x.split('_')[1:])),
-                    'post': '\t\t\tOptionType::MAX => 99\n' +
-                            '\t\t}\n\t}\n}\n',
+                    'post': '}\n',
                 },
                 {
-                    'regex': r'OPT_([A-Z]+\_)+[A-Z]+',
-                    'pre': 'bitflags! {{\n\tpub flags OptionValue : libc::size_t {{\n',
-                    'line_format': '\t\tconst {0} = {1},\n',
-                    'fn': (lambda x: x),
-                    'post': '\t}\n}\n',
+                    'regex': r'OPT_(?!SYM)([A-Z]+\_)+[A-Z]+',
+                    'pre': 'bitflags! {{\n'
+                            '#[repr(C)]\n' +
+                            '    pub struct OptionValue: libc::size_t {{\n',
+                    'line_format': '        const {0} = {1};\n',
+                    'fn': (lambda x: '_'.join(x.split('_')[1:])),
+                    'post': '    }\n}\n',
                 },
                 {
-                    'regex': r'ERR_.*',
-                    'pre': 'bitflags! {{\n\tpub flags Error : u32 {{\n',
-                    'line_format': '\t\tconst {0} = {1},\n',
-                    'fn': (lambda x: x),
-                    'post': '\t}\n}\n',
+                    'regex': r'ERR_(.*)',
+                    'pre': 'bitflags! {{\n' +
+                            '#[repr(C)]\n' +
+                            '    pub struct Error: u32 {{\n',
+                    'line_format': '        const {0} = {1};\n',
+                    'fn': (lambda x: '_'.join(x.split('_')[1:])),
+                    'post': '    }\n}',
                 },
             ],
     },
@@ -128,7 +122,7 @@ template = {
             'out_file': './go/keystone/%s_const.go',
             'rules': [
                 {
-                    'regex': r'(API)_.*',
+                    'regex': r'API_.*',
                     'pre': 'const (\n',
                     'line_format': '\t{0} = {1}\n',
                     'fn': (lambda x: x),
diff --git a/bindings/rust/.gitignore b/bindings/rust/.gitignore
index ce906b8f897bcd1482cbfbd2b1205dfb4678ab8c..7a0c5013b951ff24b193adc3c07ef501bb3011c5 100644
--- a/bindings/rust/.gitignore
+++ b/bindings/rust/.gitignore
@@ -1,3 +1,4 @@
 Cargo.lock
-target/
+**/target/**
 *.bk
+keystone-sys/keystone
diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml
index 24ea58fe6b6de2d07b15303d91a51f6cbe65b61e..b41e5988af1ea6dec0dbcf2c0fc37d7eaa5d2ab5 100644
--- a/bindings/rust/Cargo.toml
+++ b/bindings/rust/Cargo.toml
@@ -1,12 +1,26 @@
 [package]
 name = "keystone"
-version = "0.9.0"
-authors = ["Remco Verhoef <remco.verhoef@dutchcoders.io>"]
+version = "0.9.1"
+authors = [
+  "Remco Verhoef <remco.verhoef@dutchcoders.io>",
+  "Tasuku SUENAGA a.k.a. gunyarakun <tasuku-s-github@titech.ac>"
+]
 description = "Rust bindings for the keystone-engine"
 license = "GPL-2.0"
 readme = "README.md"
-include = ["src/*", "tests/*", "Cargo.toml", "COPYING", "README.md"]
+repository = "https://github.com/keystone-engine/keystone"
+include = [
+  "src/*", "tests/*", "Cargo.toml", "COPYING", "README.md",
+  "keystone-sys/*"
+]
 
 [dependencies]
-libc = "0.2.*"
-bitflags = "0.7.0"
+bitflags = "1.0"
+libc = "0.2"
+keystone-sys = { path = "keystone-sys", version = "0.9.1" }
+
+[features]
+default = []
+
+use_system_keystone = ["keystone-sys/use_system_keystone"]
+build_keystone_cmake = ["keystone-sys/build_keystone_cmake"]
diff --git a/bindings/rust/Makefile b/bindings/rust/Makefile
index 3606619707ac66275376568225ded240a735ca5b..7a3f1690cac9f93d1d3c61a589a5d1a0a0c8f7d4 100644
--- a/bindings/rust/Makefile
+++ b/bindings/rust/Makefile
@@ -1,23 +1,23 @@
 # Rust binding for Keystone engine. Remco Verhoef <remco@honeytrap.io>
 
-ifndef BUILDDIR
-OBJDIR = ./build
-else
-OBJDIR = $(abspath $(BUILDDIR))/obj/bindings/rust
-endif
+.PHONY: gen_const build package clean check
 
-.PHONY: gen_const install clean check
+build: keystone-sys/keystone
+	cargo build -vv
 
-gen_const:
-	cd .. && python const_generator.py rust
-	cargo fmt
+package: keystone-sys/keystone
+	cd keystone-sys && cargo package -vv
+	cargo package -vv
 
-install:
-	cargo build
+keystone-sys/keystone:
+	rsync -a ../.. keystone-sys/keystone --exclude bindings --filter ":- ../../.gitignore"
 
 clean:
-	rm -rf target/
+	rm -rf target/ keystone-sys/target/ keystone-sys/keystone/
 
 check:
 	cargo test
 
+gen_const:
+	cd .. && python const_generator.py rust
+	cargo fmt
diff --git a/bindings/rust/README.md b/bindings/rust/README.md
index 3a40f0790264a698695dc873105250f1bdc373ec..32cb7a0e1514b3457c08440090c3cde22425433e 100644
--- a/bindings/rust/README.md
+++ b/bindings/rust/README.md
@@ -7,10 +7,10 @@ extern crate keystone;
 use keystone::*;
 
 fn main() {
-    let engine = Keystone::new(Arch::X86, MODE_32)
+    let engine = Keystone::new(Arch::X86, Mode::MODE_32)
         .expect("Could not initialize Keystone engine");
 
-    engine.option(OptionType::SYNTAX, OPT_SYNTAX_NASM)
+    engine.option(OptionType::SYNTAX, OptionValue::SYNTAX_NASM)
         .expect("Could not set option to nasm syntax");
 
     let result = engine.asm("mov ah, 0x80".to_string(), 0)
@@ -24,6 +24,24 @@ fn main() {
 }
 ```
 
+## Installation
+Add a dependency line into `Cargo.toml`.
+
+```
+[dependencies]
+keystone = "0.10.0"
+```
+
+This package attempts to build keystone. That requires cmake and c/c++ compiler.
+
+If you want to use keystone already installed in the system, specify `use_system_keystone` feature on `Cargo.toml`.
+
+```
+[dependencies.keystone]
+version = "0.10.0"
+features = ["use_system_keystone"]
+```
+
 ## Testing
 ```
 cargo test
@@ -31,6 +49,7 @@ cargo test
 
 ## Contributors
 - Remco Verhoef (@remco_verhoef)
+- Tasuku SUENAGA a.k.a. gunyarakun (@tasukuchan)
 
 Special thanks to:
 - Sébastien Duquette (@ekse) for his [unicorn-rs](https://github.com/ekse/unicorn-rs) binding
diff --git a/bindings/rust/examples/asm.rs b/bindings/rust/examples/asm.rs
index 4676a645f9ae5e9c286c73f39ca750f4fa48ad03..86f32620bbfdb741729102d5d6f8970a75fc1f1e 100644
--- a/bindings/rust/examples/asm.rs
+++ b/bindings/rust/examples/asm.rs
@@ -2,13 +2,15 @@ extern crate keystone;
 use keystone::*;
 
 fn main() {
-    let engine = Keystone::new(Arch::X86, MODE_32)
-        .expect("Could not initialize Keystone engine");
+    let engine =
+        Keystone::new(Arch::X86, Mode::MODE_32).expect("Could not initialize Keystone engine");
 
-    engine.option(OptionType::SYNTAX, OPT_SYNTAX_NASM)
+    engine
+        .option(OptionType::SYNTAX, OptionValue::SYNTAX_NASM)
         .expect("Could not set option to nasm syntax");
 
-    let result = engine.asm("mov ah, 0x80".to_string(), 0)
+    let result = engine
+        .asm("mov ah, 0x80".to_string(), 0)
         .expect("Could not assemble");
 
     println!("ASM result: {}", result);
@@ -17,4 +19,3 @@ fn main() {
         println!("Error: {}", err);
     }
 }
-
diff --git a/bindings/rust/keystone-sys/Cargo.toml b/bindings/rust/keystone-sys/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..f791327c54c129ff5e266fa347cc4c82f20db569
--- /dev/null
+++ b/bindings/rust/keystone-sys/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+name = "keystone-sys"
+version = "0.9.0"
+authors = [
+  "Remco Verhoef <remco.verhoef@dutchcoders.io>",
+  "Tasuku SUENAGA a.k.a. gunyarakun <tasuku-s-github@titech.ac>"
+]
+description = "Rust bindings for the keystone assembler"
+repository = "https://github.com/keystone-engine/keystone"
+documentation = "https://docs.rs/keystone/"
+license = "GPL-2.0"
+build = "build.rs"
+exclude = [
+  "keystone/build/**"
+]
+
+[build-dependencies]
+build-helper = "0.1"
+os_type = "2.0"
+pkg-config = { optional = true, version = "0.3" }
+
+[dependencies]
+bitflags = "1.0"
+libc = "0.2"
+
+[features]
+default = []
+
+use_system_keystone = ["pkg-config"]
+build_keystone_cmake = []
diff --git a/bindings/rust/keystone-sys/build.rs b/bindings/rust/keystone-sys/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2f698ab7035eeca10c8acffe517d96ccddb9b316
--- /dev/null
+++ b/bindings/rust/keystone-sys/build.rs
@@ -0,0 +1,67 @@
+#[cfg(feature = "use_system_keystone")]
+extern crate pkg_config;
+
+use std::env;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn build_with_cmake() {
+    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
+    let cmake_dir = PathBuf::from("keystone");
+    let build_dir = cmake_dir.join("build");
+
+    if !cmake_dir.exists() {
+        run(Command::new("ln").arg("-s").arg("../../..").arg("keystone"));
+    }
+
+    run(Command::new("mkdir")
+        .current_dir(&cmake_dir)
+        .arg("-p")
+        .arg("build"));
+
+    run(Command::new("../make-share.sh").current_dir(&build_dir));
+
+    run(Command::new("cmake").current_dir(&build_dir).args(&[
+        &format!("-DCMAKE_INSTALL_PREFIX={}", out_dir.display()),
+        "-DCMAKE_BUILD_TYPE=Release",
+        "-DBUILD_LIBS_ONLY=1",
+        "-DCMAKE_OSX_ARCHITECTURES=",
+        "-DBUILD_SHARED_LIBS=ON",
+        "-DLLVM_TARGET_ARCH=host",
+        "-G",
+        "Unix Makefiles",
+        "..",
+    ]));
+
+    run(Command::new("make").current_dir(&build_dir).arg("install"));
+
+    println!("cargo:rustc-link-search=native={}/lib", out_dir.display());
+    println!("cargo:rustc-link-lib=keystone");
+}
+
+fn main() {
+    if cfg!(feature = "use_system_keystone") {
+        #[cfg(feature = "use_system_keystone")]
+        pkg_config::find_library("keystone").expect("Could not find system keystone");
+    } else {
+        build_with_cmake();
+    }
+}
+
+fn run(cmd: &mut Command) {
+    println!("run: {:?}", cmd);
+    let status = match cmd.status() {
+        Ok(s) => s,
+        Err(ref e) => fail(&format!("failed to execute command: {}", e)),
+    };
+    if !status.success() {
+        fail(&format!(
+            "command did not execute successfully, got: {}",
+            status
+        ));
+    }
+}
+
+fn fail(s: &str) -> ! {
+    panic!("\n{}\n\nbuild script failed, must exit now", s);
+}
diff --git a/bindings/rust/keystone-sys/src/keystone_const.rs b/bindings/rust/keystone-sys/src/keystone_const.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c81f3240c0cf953365bb4619888c4a9c530c57b3
--- /dev/null
+++ b/bindings/rust/keystone-sys/src/keystone_const.rs
@@ -0,0 +1,119 @@
+#![allow(non_camel_case_types)]
+// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystone_const.rs]
+use libc;
+
+pub const API_MAJOR: u32 = 0;
+pub const API_MINOR: u32 = 9;
+
+bitflags! {
+#[repr(C)]
+    pub struct Mode: u32 {
+        const LITTLE_ENDIAN = 0;
+        const BIG_ENDIAN = 1073741824;
+        const ARM = 1;
+        const THUMB = 16;
+        const V8 = 64;
+        const MICRO = 16;
+        const MIPS3 = 32;
+        const MIPS32R6 = 64;
+        const MIPS32 = 4;
+        const MIPS64 = 8;
+        const MODE_16 = 2;
+        const MODE_32 = 4;
+        const MODE_64 = 8;
+        const PPC32 = 4;
+        const PPC64 = 8;
+        const QPX = 16;
+        const SPARC32 = 4;
+        const SPARC64 = 8;
+        const V9 = 16;
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum Arch {
+    ARM = 1,
+    ARM64 = 2,
+    MIPS = 3,
+    X86 = 4,
+    PPC = 5,
+    SPARC = 6,
+    SYSTEMZ = 7,
+    HEXAGON = 8,
+    EVM = 9,
+    MAX = 10,
+}
+
+#[repr(C)]
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum OptionType {
+    SYNTAX = 1,
+    SYM_RESOLVER = 2,
+}
+
+bitflags! {
+#[repr(C)]
+    pub struct OptionValue: libc::size_t {
+        const SYNTAX_INTEL = 1;
+        const SYNTAX_ATT = 2;
+        const SYNTAX_NASM = 4;
+        const SYNTAX_MASM = 8;
+        const SYNTAX_GAS = 16;
+        const SYNTAX_RADIX16 = 32;
+    }
+}
+
+bitflags! {
+#[repr(C)]
+    pub struct Error: u32 {
+        const ASM = 128;
+        const ASM_ARCH = 512;
+        const OK = 0;
+        const NOMEM = 1;
+        const ARCH = 2;
+        const HANDLE = 3;
+        const MODE = 4;
+        const VERSION = 5;
+        const OPT_INVALID = 6;
+        const ASM_EXPR_TOKEN = 128;
+        const ASM_DIRECTIVE_VALUE_RANGE = 129;
+        const ASM_DIRECTIVE_ID = 130;
+        const ASM_DIRECTIVE_TOKEN = 131;
+        const ASM_DIRECTIVE_STR = 132;
+        const ASM_DIRECTIVE_COMMA = 133;
+        const ASM_DIRECTIVE_RELOC_NAME = 134;
+        const ASM_DIRECTIVE_RELOC_TOKEN = 135;
+        const ASM_DIRECTIVE_FPOINT = 136;
+        const ASM_DIRECTIVE_UNKNOWN = 137;
+        const ASM_DIRECTIVE_EQU = 138;
+        const ASM_DIRECTIVE_INVALID = 139;
+        const ASM_VARIANT_INVALID = 140;
+        const ASM_EXPR_BRACKET = 141;
+        const ASM_SYMBOL_MODIFIER = 142;
+        const ASM_SYMBOL_REDEFINED = 143;
+        const ASM_SYMBOL_MISSING = 144;
+        const ASM_RPAREN = 145;
+        const ASM_STAT_TOKEN = 146;
+        const ASM_UNSUPPORTED = 147;
+        const ASM_MACRO_TOKEN = 148;
+        const ASM_MACRO_PAREN = 149;
+        const ASM_MACRO_EQU = 150;
+        const ASM_MACRO_ARGS = 151;
+        const ASM_MACRO_LEVELS_EXCEED = 152;
+        const ASM_MACRO_STR = 153;
+        const ASM_MACRO_INVALID = 154;
+        const ASM_ESC_BACKSLASH = 155;
+        const ASM_ESC_OCTAL = 156;
+        const ASM_ESC_SEQUENCE = 157;
+        const ASM_ESC_STR = 158;
+        const ASM_TOKEN_INVALID = 159;
+        const ASM_INSN_UNSUPPORTED = 160;
+        const ASM_FIXUP_INVALID = 161;
+        const ASM_LABEL_INVALID = 162;
+        const ASM_FRAGMENT_INVALID = 163;
+        const ASM_INVALIDOPERAND = 512;
+        const ASM_MISSINGFEATURE = 513;
+        const ASM_MNEMONICFAIL = 514;
+    }
+}
diff --git a/bindings/rust/keystone-sys/src/lib.rs b/bindings/rust/keystone-sys/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c063c48a336042c98f473a963361b5a49edbf647
--- /dev/null
+++ b/bindings/rust/keystone-sys/src/lib.rs
@@ -0,0 +1,59 @@
+//! Keystone Assembler Engine (www.keystone-engine.org) */
+//! By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
+//! Rust bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
+//!
+
+#[macro_use]
+extern crate bitflags;
+extern crate libc;
+
+pub mod keystone_const;
+
+use std::fmt;
+use std::ffi::CStr;
+use std::os::raw::c_char;
+use keystone_const::{Arch, Error, Mode, OptionType, OptionValue};
+
+#[allow(non_camel_case_types)]
+pub type ks_handle = libc::size_t;
+
+#[link(name = "keystone")]
+extern "C" {
+    pub fn ks_version(major: *const u32, minor: *const u32) -> u32;
+    pub fn ks_arch_supported(arch: Arch) -> bool;
+    pub fn ks_open(arch: Arch, mode: Mode, engine: *mut ks_handle) -> Error;
+    pub fn ks_asm(
+        engine: ks_handle,
+        string: *const c_char,
+        address: u64,
+        encoding: *mut *mut libc::c_uchar,
+        encoding_size: *mut libc::size_t,
+        stat_count: *mut libc::size_t,
+    ) -> u32;
+    pub fn ks_errno(engine: ks_handle) -> Error;
+    pub fn ks_strerror(error_code: Error) -> *const c_char;
+    pub fn ks_option(engine: ks_handle, opt_type: OptionType, value: OptionValue) -> Error;
+    pub fn ks_close(engine: ks_handle);
+    pub fn ks_free(encoding: *mut libc::c_uchar);
+}
+
+impl Error {
+    pub fn msg(&self) -> String {
+        error_msg(*self)
+    }
+}
+
+/// Return a string describing given error code.
+pub fn error_msg(error: Error) -> String {
+    unsafe {
+        CStr::from_ptr(ks_strerror(error))
+            .to_string_lossy()
+            .into_owned()
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.msg())
+    }
+}
diff --git a/bindings/rust/src/enums.rs b/bindings/rust/src/enums.rs
deleted file mode 100644
index 45516be71266e26d601742ec671ee6d93763b056..0000000000000000000000000000000000000000
--- a/bindings/rust/src/enums.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-pub use keystone_const::*;
-
-#[repr(u32)]
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum Arch {
-    ARM = KS_ARCH_ARM,
-    ARM64 =KS_ARCH_ARM64,
-    MIPS = KS_ARCH_MIPS,
-    X86 = KS_ARCH_X86,
-    PPC = KS_ARCH_PPC,
-    SPARC = KS_ARCH_SPARC,
-    SYSTEMZ = KS_ARCH_SYSTEMZ,
-    HEXAGON = KS_ARCH_HEXAGON,
-}
-
-#[repr(u32)]
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum Mode {
-    LittleEndian = KS_MODE_LITTLE_ENDIAN,
-    BigEndian = KS_MODE_BIG_ENDIAN,
-    /*
-    ARM = KS_MODE_ARM,
-    THUMB = KS_MODE_THUMB,
-    V8 = KS_MODE_V8,
-    MICRO = KS_MODE_MICRO,
-    MIPS3 = KS_MODE_MIPS3,
-    MIPS32R6 = KS_MODE_MIPS32R6,
-    MIPS32 = KS_MODE_MIPS32,
-    MIPS64 = KS_MODE_MIPS64,
-    SIZE_16= KS_MODE_16,
-    */
-    Mode32 = KS_MODE_32,
-    /*
-    SIZE_64 = KS_MODE_64,
-    PPC32 = KS_MODE_PPC32,
-    PPC64 = KS_MODE_PPC64,
-    QPX = KS_MODE_QPX,
-    SPARC32 = KS_MODE_SPARC32,
-    SPARC64 = KS_MODE_SPARC64,
-    V9 = KS_MODE_V9,
-    */
-}
-
-#[repr(u32)]
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum Error {
-    Ok = KS_ERR_OK,
-    // ASM = KS_ERR_ASM,
-    // ASM_ARCH = KS_ERR_ASM_ARCH,
-    NoMem = KS_ERR_NOMEM,
-    Arch = KS_ERR_ARCH,
-    Handle = KS_ERR_HANDLE,
-    Mode = KS_ERR_MODE,
-    Version = KS_ERR_VERSION,
-    OptionInvalid = KS_ERR_OPT_INVALID,
-    AsmExprToken = KS_ERR_ASM_EXPR_TOKEN,
-    AsmDirectiveValueRange = KS_ERR_ASM_DIRECTIVE_VALUE_RANGE,
-    AsmDirectiveToken = KS_ERR_ASM_DIRECTIVE_ID,
-    DirectiveToken = KS_ERR_ASM_DIRECTIVE_TOKEN,
-    DirectiveStr =  KS_ERR_ASM_DIRECTIVE_STR,
-    DirectiveComma =  KS_ERR_ASM_DIRECTIVE_COMMA,
-    DirectiveRelocName =  KS_ERR_ASM_DIRECTIVE_RELOC_NAME,
-    DirectiveRelocToken =  KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN,
-    DirectiveFPoint =  KS_ERR_ASM_DIRECTIVE_FPOINT,
-    VariantInvalid =  KS_ERR_ASM_VARIANT_INVALID,
-    ExprBracket =  KS_ERR_ASM_EXPR_BRACKET,
-    SymbolModifier =  KS_ERR_ASM_SYMBOL_MODIFIER,
-    RParen =  KS_ERR_ASM_RPAREN,
-    StatToken =  KS_ERR_ASM_STAT_TOKEN,
-    AsmUnsupported = KS_ERR_ASM_UNSUPPORTED,
-    AsmMacroToken = KS_ERR_ASM_MACRO_TOKEN,
-    AsmMacroParen = KS_ERR_ASM_MACRO_PAREN,
-    AsmMacroEQU = KS_ERR_ASM_MACRO_EQU,
-    AsmMacroArgs = KS_ERR_ASM_MACRO_ARGS,
-    AsmMacroLevelsExceed = KS_ERR_ASM_MACRO_LEVELS_EXCEED,
-    AsmEscBackslash = KS_ERR_ASM_ESC_BACKSLASH,
-    AsmEscOctal = KS_ERR_ASM_ESC_OCTAL,
-    AsmEscSequence =  KS_ERR_ASM_ESC_SEQUENCE,
-    AsmInvalidOperand = KS_ERR_ASM_INVALIDOPERAND,
-    AsmMissingFeature = KS_ERR_ASM_MISSINGFEATURE,
-    AsmMNemonicFail = KS_ERR_ASM_MNEMONICFAIL,
-}
-
-#[repr(u32)]
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum OptionType {
-    Syntax = KS_OPT_SYNTAX,
-    SYNTAX2 = KS_OPT_SYNTAX_NASM,
-}
-
-#[repr(u32)]
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum OptionValue {
-    SyntaxIntel = KS_OPT_SYNTAX_INTEL,
-    SyntaxATT = KS_OPT_SYNTAX_ATT,
-    SyntaxNASM = KS_OPT_SYNTAX_NASM,
-    SyntaxMASM = KS_OPT_SYNTAX_MASM,
-    SyntaxGAS = KS_OPT_SYNTAX_GAS,
-}
-
-
diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/src/ffi.rs
deleted file mode 100644
index 1fd2389557fe0d725e551ff857dbbe08a382c39d..0000000000000000000000000000000000000000
--- a/bindings/rust/src/ffi.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Keystone Assembler Engine (www.keystone-engine.org) */
-//! By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
-//! Rust bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
-//!
-
-use libc;
-use std::os::raw::c_char;
-
-use ks_handle;
-
-#[link(name = "keystone")]
-extern "C" {
-    pub fn ks_version(major: *const u32, minor: *const u32) -> u32;
-    pub fn ks_arch_supported(arch: u32) -> bool;
-    pub fn ks_open(arch: u32, mode: u32, engine: *mut ks_handle) -> u32;
-    pub fn ks_asm(engine: ks_handle,
-                  string: *const c_char,
-                  address: u64,
-                  encoding: *mut *mut libc::c_uchar,
-                  encoding_size: *mut libc::size_t,
-                  stat_count: *mut libc::size_t)
-                  -> u32;
-    pub fn ks_errno(engine: ks_handle) -> u32;
-    pub fn ks_strerror(error_code: u32) -> *const c_char;
-    pub fn ks_option(engine: ks_handle, type_: u32, value: libc::size_t) -> u32;
-    pub fn ks_close(engine: ks_handle);
-    pub fn ks_free(encoding: *mut libc::c_uchar);
-}
diff --git a/bindings/rust/src/keystone_const.rs b/bindings/rust/src/keystone_const.rs
deleted file mode 100644
index d7f78963b98c4c96953b520757d683f39f1d5842..0000000000000000000000000000000000000000
--- a/bindings/rust/src/keystone_const.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystone_const.rs]
-extern crate libc;
-
-
-pub const KS_API_MAJOR : u32 = 0;
-pub const KS_API_MINOR : u32 = 9;
-pub const KS_ARCH_ARM : u32 = 1;
-pub const KS_ARCH_ARM64 : u32 = 2;
-pub const KS_ARCH_MIPS : u32 = 3;
-pub const KS_ARCH_X86 : u32 = 4;
-pub const KS_ARCH_PPC : u32 = 5;
-pub const KS_ARCH_SPARC : u32 = 6;
-pub const KS_ARCH_SYSTEMZ : u32 = 7;
-pub const KS_ARCH_HEXAGON : u32 = 8;
-pub const KS_ARCH_EVM : u32 = 9;
-pub const KS_ARCH_MAX : u32 = 10;
-
-
-bitflags! {
-	pub flags Mode : u32 {
-		const MODE_LITTLE_ENDIAN = 0,
-		const MODE_BIG_ENDIAN = 1073741824,
-		const MODE_ARM = 1,
-		const MODE_THUMB = 16,
-		const MODE_V8 = 64,
-		const MODE_MICRO = 16,
-		const MODE_MIPS3 = 32,
-		const MODE_MIPS32R6 = 64,
-		const MODE_MIPS32 = 4,
-		const MODE_MIPS64 = 8,
-		const MODE_16 = 2,
-		const MODE_32 = 4,
-		const MODE_64 = 8,
-		const MODE_PPC32 = 4,
-		const MODE_PPC64 = 8,
-		const MODE_QPX = 16,
-		const MODE_SPARC32 = 4,
-		const MODE_SPARC64 = 8,
-		const MODE_V9 = 16,
-	}
-}
-
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum Arch {
-	ARM,
-	ARM64,
-	MIPS,
-	X86,
-	PPC,
-	SPARC,
-	SYSTEMZ,
-	HEXAGON,
-	EVM,
-	MAX,
-}
-
-
-impl Arch {
-	#[inline]
-	pub fn val(&self) -> u32 {
-		match *self {
-			Arch::ARM => 1,
-			Arch::ARM64 => 2,
-			Arch::MIPS => 3,
-			Arch::X86 => 4,
-			Arch::PPC => 5,
-			Arch::SPARC => 6,
-			Arch::SYSTEMZ => 7,
-			Arch::HEXAGON => 8,
-			Arch::EVM => 9,
-			Arch::MAX => 10,
-		}
-	}
-}
-
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum OptionType {
-	SYNTAX,
-	MAX,
-}
-
-impl OptionType {
-	#[inline]
-	pub fn val(&self) -> u32 {
-		match *self {
-			OptionType::SYNTAX => 1,
-			OptionType::MAX => 99
-		}
-	}
-}
-
-bitflags! {
-	pub flags OptionValue : libc::size_t {
-		const OPT_SYM_RESOLVER = 2,
-		const OPT_SYNTAX_INTEL = 1,
-		const OPT_SYNTAX_ATT = 2,
-		const OPT_SYNTAX_NASM = 4,
-		const OPT_SYNTAX_MASM = 8,
-		const OPT_SYNTAX_GAS = 16,
-		const OPT_SYNTAX_RADIX16 = 32,
-	}
-}
-
-bitflags! {
-	pub flags Error : u32 {
-		const ERR_ASM = 128,
-		const ERR_ASM_ARCH = 512,
-		const ERR_OK = 0,
-		const ERR_NOMEM = 1,
-		const ERR_ARCH = 2,
-		const ERR_HANDLE = 3,
-		const ERR_MODE = 4,
-		const ERR_VERSION = 5,
-		const ERR_OPT_INVALID = 6,
-		const ERR_ASM_EXPR_TOKEN = 128,
-		const ERR_ASM_DIRECTIVE_VALUE_RANGE = 129,
-		const ERR_ASM_DIRECTIVE_ID = 130,
-		const ERR_ASM_DIRECTIVE_TOKEN = 131,
-		const ERR_ASM_DIRECTIVE_STR = 132,
-		const ERR_ASM_DIRECTIVE_COMMA = 133,
-		const ERR_ASM_DIRECTIVE_RELOC_NAME = 134,
-		const ERR_ASM_DIRECTIVE_RELOC_TOKEN = 135,
-		const ERR_ASM_DIRECTIVE_FPOINT = 136,
-		const ERR_ASM_DIRECTIVE_UNKNOWN = 137,
-		const ERR_ASM_DIRECTIVE_EQU = 138,
-		const ERR_ASM_DIRECTIVE_INVALID = 139,
-		const ERR_ASM_VARIANT_INVALID = 140,
-		const ERR_ASM_EXPR_BRACKET = 141,
-		const ERR_ASM_SYMBOL_MODIFIER = 142,
-		const ERR_ASM_SYMBOL_REDEFINED = 143,
-		const ERR_ASM_SYMBOL_MISSING = 144,
-		const ERR_ASM_RPAREN = 145,
-		const ERR_ASM_STAT_TOKEN = 146,
-		const ERR_ASM_UNSUPPORTED = 147,
-		const ERR_ASM_MACRO_TOKEN = 148,
-		const ERR_ASM_MACRO_PAREN = 149,
-		const ERR_ASM_MACRO_EQU = 150,
-		const ERR_ASM_MACRO_ARGS = 151,
-		const ERR_ASM_MACRO_LEVELS_EXCEED = 152,
-		const ERR_ASM_MACRO_STR = 153,
-		const ERR_ASM_MACRO_INVALID = 154,
-		const ERR_ASM_ESC_BACKSLASH = 155,
-		const ERR_ASM_ESC_OCTAL = 156,
-		const ERR_ASM_ESC_SEQUENCE = 157,
-		const ERR_ASM_ESC_STR = 158,
-		const ERR_ASM_TOKEN_INVALID = 159,
-		const ERR_ASM_INSN_UNSUPPORTED = 160,
-		const ERR_ASM_FIXUP_INVALID = 161,
-		const ERR_ASM_LABEL_INVALID = 162,
-		const ERR_ASM_FRAGMENT_INVALID = 163,
-		const ERR_ASM_INVALIDOPERAND = 512,
-		const ERR_ASM_MISSINGFEATURE = 513,
-		const ERR_ASM_MNEMONICFAIL = 514,
-	}
-}
-
diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs
index b113e1fc150ec3112af0d1a72a9f408fc20e627f..5bcd5bfdded6ac0aaf4cca2170afb233547477d9 100644
--- a/bindings/rust/src/lib.rs
+++ b/bindings/rust/src/lib.rs
@@ -4,56 +4,28 @@
 //!
 //! ```rust
 //! extern crate keystone;
-//! use keystone::{Keystone, Arch, OptionType};
+//! use keystone::{Keystone, Arch, Mode, OptionType, OptionValue};
 //!
 //! fn main() {
-//!     let engine = Keystone::new(Arch::X86, keystone::MODE_32)
+//!     let engine = Keystone::new(Arch::X86, Mode::MODE_32)
 //!         .expect("Could not initialize Keystone engine");
-//!     engine.option(OptionType::SYNTAX, keystone::OPT_SYNTAX_NASM)
+//!     engine.option(OptionType::SYNTAX, OptionValue::SYNTAX_NASM)
 //!         .expect("Could not set option to nasm syntax");
 //!     let result = engine.asm("mov ah, 0x80".to_string(), 0)
 //!         .expect("Could not assemble");
 //! }
 //! ```
 
-#![doc(html_root_url="https://keystone/doc/here/v1")]
+#![doc(html_root_url = "https://keystone/doc/here/v1")]
 
-#[macro_use]
-extern crate bitflags;
+extern crate keystone_sys as ffi;
 extern crate libc;
 
-pub mod ffi;
-// pub mod enums;
-pub mod keystone_const;
-// pub mod arm64_const;
-// pub mod arm_const;
-// pub mod hexagon_const;
-// pub mod mips_const;
-// pub mod ppc_const;
-// pub mod sparc_const;
-// pub mod systemz_const;
-// pub mod x86_const;
-
-use std::ffi::CStr;
 use std::ffi::CString;
 use std::fmt;
 
-pub use keystone_const::*;
-
-#[allow(non_camel_case_types)]
-pub type ks_handle = libc::size_t;
-
-impl Error {
-    pub fn msg(&self) -> String {
-        error_msg(*self)
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.msg())
-    }
-}
+pub use ffi::keystone_const::*;
+pub use ffi::ks_handle;
 
 #[derive(Debug, PartialEq)]
 pub struct AsmResult {
@@ -73,7 +45,7 @@ impl fmt::Display for AsmResult {
 }
 
 pub fn bindings_version() -> (u32, u32) {
-    (KS_API_MAJOR, KS_API_MINOR)
+    (API_MAJOR, API_MINOR)
 }
 
 /// Return tuple `(major, minor)` API version numbers.
@@ -89,12 +61,15 @@ pub fn version() -> (u32, u32) {
 
 /// Return tuple `(major, minor)` API version numbers.
 pub fn arch_supported(arch: Arch) -> bool {
-    unsafe { ffi::ks_arch_supported(arch.val()) }
+    unsafe { ffi::ks_arch_supported(arch) }
 }
 
-/// Return a string describing given error code.
 pub fn error_msg(error: Error) -> String {
-    unsafe { CStr::from_ptr(ffi::ks_strerror(error.bits())).to_string_lossy().into_owned() }
+    unsafe {
+        CStr::from_ptr(ffi::ks_strerror(error.bits()))
+            .to_string_lossy()
+            .into_owned()
+    }
 }
 
 pub struct Keystone {
@@ -105,15 +80,13 @@ impl Keystone {
     /// Create new instance of Keystone engine.
     pub fn new(arch: Arch, mode: Mode) -> Result<Keystone, Error> {
         if version() != bindings_version() {
-            return Err(ERR_VERSION);
+            return Err(Error::VERSION);
         }
 
         let mut handle: ks_handle = 0;
 
-        let err = Error::from_bits_truncate(unsafe {
-            ffi::ks_open(arch.val(), mode.bits(), &mut handle)
-        });
-        if err == ERR_OK {
+        let err = unsafe { ffi::ks_open(arch, mode, &mut handle) };
+        if err == Error::OK {
             Ok(Keystone { handle: handle })
         } else {
             Err(err)
@@ -122,8 +95,8 @@ impl Keystone {
 
     /// Report the last error number when some API function fail.
     pub fn error(&self) -> Result<(), Error> {
-        let err = Error::from_bits_truncate(unsafe { ffi::ks_errno(self.handle) });
-        if err == ERR_OK {
+        let err = unsafe { ffi::ks_errno(self.handle) };
+        if err == Error::OK {
             Ok(())
         } else {
             Err(err)
@@ -131,11 +104,9 @@ impl Keystone {
     }
 
     /// Set option for Keystone engine at runtime
-    pub fn option(&self, type_: OptionType, value: OptionValue) -> Result<(), Error> {
-        let err = Error::from_bits_truncate(unsafe {
-            ffi::ks_option(self.handle, type_.val(), value.bits())
-        });
-        if err == ERR_OK {
+    pub fn option(&self, option_type: OptionType, value: OptionValue) -> Result<(), Error> {
+        let err = unsafe { ffi::ks_option(self.handle, option_type, value) };
+        if err == Error::OK {
             Ok(())
         } else {
             Err(err)
@@ -155,15 +126,17 @@ impl Keystone {
         let mut ptr: *mut libc::c_uchar = std::ptr::null_mut();
 
         let err = Error::from_bits_truncate(unsafe {
-            ffi::ks_asm(self.handle,
-                        s.as_ptr(),
-                        address,
-                        &mut ptr,
-                        &mut size,
-                        &mut stat_count)
+            ffi::ks_asm(
+                self.handle,
+                s.as_ptr(),
+                address,
+                &mut ptr,
+                &mut size,
+                &mut stat_count,
+            )
         });
 
-        if err == ERR_OK {
+        if err == Error::OK {
             let bytes_slice = unsafe { std::slice::from_raw_parts(ptr, size) };
             let bytes = bytes_slice.to_vec();
 
@@ -174,10 +147,10 @@ impl Keystone {
             Ok(AsmResult {
                 size: size as u32,
                 stat_count: stat_count as u32,
-                bytes
+                bytes,
             })
         } else {
-            let err = Error::from_bits_truncate(unsafe { ffi::ks_errno(self.handle) });
+            let err = unsafe { ffi::ks_errno(self.handle) };
             Err(err)
         }
     }
diff --git a/bindings/rust/tests/keystone.rs b/bindings/rust/tests/keystone.rs
index ed96ecec2f6f06187a08a5b6bba4a366284be9b1..f5d3e39db34eb2067b68c2d3ff1ec36c998d4920 100644
--- a/bindings/rust/tests/keystone.rs
+++ b/bindings/rust/tests/keystone.rs
@@ -1,6 +1,6 @@
 extern crate keystone;
 
-use keystone::{Keystone, Arch, OptionType};
+use keystone::{Arch, Error, Keystone, Mode, OptionType, OptionValue};
 
 #[test]
 fn version() {
@@ -18,31 +18,33 @@ fn arch_supported() {
 fn asm() {
     let asm = String::from("mov ah, 0x80\n nop\n mov al, 0x81\n");
 
-    let engine = Keystone::new(Arch::X86, keystone::MODE_LITTLE_ENDIAN | keystone::MODE_32)
+    let engine = Keystone::new(Arch::X86, Mode::LITTLE_ENDIAN | Mode::MODE_32)
         .expect("Could not initialize Keystone engine");
 
-    engine.option(OptionType::SYNTAX, keystone::OPT_SYNTAX_NASM)
+    engine
+        .option(OptionType::SYNTAX, OptionValue::SYNTAX_NASM)
         .expect("Could not set option to nasm syntax");
 
-    let result = engine.asm(asm, 0)
-        .expect("Could not assemble");
+    let result = engine.asm(asm, 0).expect("Could not assemble");
 
     print!("{0:?}", result.bytes);
-    assert_eq!(result.bytes,[0xb4,0x80, 0x90, 0xb0, 0x81]);
+    assert_eq!(result.bytes, [0xb4, 0x80, 0x90, 0xb0, 0x81]);
 }
 
 #[test]
 fn invalid_asm() {
     let asm = String::from("invalid asm");
 
-    let engine = Keystone::new(Arch::X86, keystone::MODE_32)
-        .expect("Could not initialize Keystone engine");
+    let engine =
+        Keystone::new(Arch::X86, Mode::MODE_32).expect("Could not initialize Keystone engine");
 
     let result = engine.asm(asm, 0);
     let err = result.unwrap_err();
 
-    assert_eq!(err, keystone::ERR_ASM_MNEMONICFAIL);
+    assert_eq!(err, Error::ASM_MNEMONICFAIL);
     assert_eq!(err.msg(), "Invalid mnemonic (KS_ERR_ASM_MNEMONICFAIL)");
-    assert_eq!(format!("{}", err), "Invalid mnemonic (KS_ERR_ASM_MNEMONICFAIL)");
+    assert_eq!(
+        format!("{}", err),
+        "Invalid mnemonic (KS_ERR_ASM_MNEMONICFAIL)"
+    );
 }
-