Repository: SUPERAndroidAnalyzer/abxml-rs (language: rust)

Issue:
Add Crates.io badges
We are not taking advantage of the new `Cargo.toml` keywords, and they should be added. This is the list of keywords we should add in the `[badges]` section:

 - `travis-ci = { repository = "...", branch = "master" }`: Adds Travis-CI build information.
 - `appveyor = { repository = "...", branch = "master", service = "github" }`: Adds Appveyor Windows build information, depends on #58.
 - `coveralls = { repository = "...", branch = "master", service = "github" }`: Adds Coveralls coverage report, but we might want to switch to Codecov, since it works much better (#59). In that case we would need to add `codecov = { repository = "...", branch = "master", service = "github" }`.
 - `is-it-maintained-issue-resolution = { repository = "..." }`: Adds information about issue resolution time.
 - `is-it-maintained-open-issues = { repository = "..." }`: Adds information about open issues.
 - `maintenance = { status = "..." }`: Adds information about the current maintenance status. Options are `actively-developed`, `passively-maintained`, `as-is`, `none`, `experimental`, `looking-for-maintainer` and `deprecated`. I would propose `passively-maintained`, but suggestions are welcome.

We should also add the `categories` keyword to the `[package]` section.

For more information, check the [Package metadata][package_metadata] section in the Cargo documentation.

[package_metadata]: https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 3ffa39b13..1c8242cc9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ target
 Cargo.lock
 AndroidManifest*.xml
 *.bk
-.vagrant
\ No newline at end of file
+.vagrant
+fuzz/crash-*
diff --git a/.travis.yml b/.travis.yml
index c53384d44..e16003c4d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,10 @@
 language: rust
-cache: cargo
+# cache: cargo
 dist: trusty
-sudo: false
+sudo: true
 os:
   - linux
-
-env:
-  global:
-    -cache: cargo
+  - osx
 
 addons:
   apt:
@@ -15,10 +12,11 @@ addons:
       - libcurl4-openssl-dev
       - libelf-dev
       - libdw-dev
-      - binutils-dev
       - cmake
-    sources:
-      - kalakris-cmake
+      - gcc
+      - binutils-dev
+      - libiberty-dev
+      - zlib1g-dev
 
 rust:
   - nightly
@@ -26,30 +24,29 @@ rust:
   - stable
   - 1.20.0
 
-matrix:
-  allow_failures:
-    - rust: nightly
-
 before_script:
-  - |
-      cargo install cargo-travis || true  &&
-      export PATH=$HOME/.cargo/bin:$PATH
-  - (test $TRAVIS_RUST_VERSION != "nightly" || cargo install rustfmt-nightly --force)
+  - export PATH=$PATH:~/.cargo/bin
+  - ./travis-helper.sh install_deps
 
 script:
-  - |
-    cargo build &&
-    cargo build --example converter &&
-    cargo build --example exporter &&
-    cargo test
-  - (test $TRAVIS_RUST_VERSION != "nightly" || cargo fmt -- --write-mode=diff)
+  - cargo build
+  - cargo build --example converter
+  - cargo build --example exporter
+  - cargo test
+  - cargo package
+  - ./travis-helper.sh clippy_run
+  - ./travis-helper.sh fmt_run
 
 after_success:
-  - cargo coveralls
+  - ./travis-helper.sh upload_code_coverage
+  - ./travis-helper.sh upload_documentation
 
 notifications:
   email:
     recipients:
-      - gnieto.talo@gmail.com
+      - razican@protonmail.ch
+      - brunoop@protonmail.ch
+      - sergiodlo@protonmail.com
+      - jaimesr@protonmail.ch
     on_success: change
     on_failure: always
diff --git a/Cargo.toml b/Cargo.toml
index aeb66f23c..267b9292c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,24 +1,33 @@
 [package]
 name = "abxml"
-version = "0.3.0"
+version = "0.4.0"
 license = "MIT/Apache-2.0"
 authors = [
     "Guillem Nieto <gnieto.talo@gmail.com>",
     "Iban Eguia <razican@protonmail.ch>"
 ]
-repository = "https://github.com/gnieto/abxml-rs"
+repository = "https://github.com/SUPERAndroidAnalyzer/abxml-rs"
 description = """
 Parser for resources.arsc contained on APKs and binary XML decompresser
 """
 keywords = ["android", "arsc", "apk", "parser"]
+categories = ["parser-implementations", "parsing"]
+
+[badges]
+travis-ci = { repository = "SUPERAndroidAnalyzer/abxml-rss", branch = "master" }
+appveyor = { repository = "SUPERAndroidAnalyzer/abxml-rs", branch = "master", service = "github" }
+codecov = { repository = "SUPERAndroidAnalyzer/abxml-rs", branch = "master", service = "github" }
+is-it-maintained-issue-resolution = { repository = "SUPERAndroidAnalyzer/abxml-rs" }
+is-it-maintained-open-issues = { repository = "SUPERAndroidAnalyzer/abxml-rs" }
+maintenance = { status = "passively-maintained" }
 
 [dependencies]
-byteorder = "1.2.1"
-error-chain = "0.11.0"
-ansi_term = "0.10.2"
+failure = "0.1.1"
+byteorder = "1.2.2"
+ansi_term = "0.11.0"
 log = "0.4.1"
-env_logger = "0.5.0"
-zip = { version = "0.3.0", optional = true}
+env_logger = "0.5.6"
+zip = { version = "0.3.1", optional = true}
 encoding = "0.2.33"
 xml-rs = "0.7.0"
 
diff --git a/README.md b/README.md
index 862e26316..1db125462 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-[![Coverage Status](https://coveralls.io/repos/github/gnieto/abxml-rs/badge.svg?branch=develop)](https://coveralls.io/github/gnieto/abxml-rs?branch=develop)
-[![Build Status](https://travis-ci.org/gnieto/abxml-rs.svg?branch=develop)](https://travis-ci.org/gnieto/abxml-rs)
+[![Coverage Status][coverage_badge]][coverage_link]
+[![Build Status][status_badge]][status_link]
 
 # ABXML
 
@@ -9,7 +9,7 @@ The code is deeply inspired on Apktool: Without it, this library wouldn't exist.
 
 ## Quick example
 
-The easiest way to use the library is using the helper struct `APK` to decompress and decode it to the filesystem. 
+The easiest way to use the library is using the helper struct `APK` to decompress and decode it to the filesystem.
 
 ```rust
 extern crate abxml;
@@ -48,7 +48,7 @@ impl<'a> ChunkVisitor<'a> for PrintVisitor {
 fn main() {
     let data = [];
     let mut visitor = PrintVisitor;
-    
+
     Executor::xml(&data, &mut visitor);
 }
 ```
@@ -79,4 +79,9 @@ After that, you should be able to run:
 ```
 
 You should see, per each file, if the output of the library matches with the output of Apktool.
-In case that there is some difference, it will print the diff of the outputs.
\ No newline at end of file
+In case that there is some difference, it will print the diff of the outputs.
+
+[coverage_badge]: https://codecov.io/gh/SUPERAndroidAnalyzer/abxml-rs/branch/develop/graph/badge.svg
+[coverage_link]: https://codecov.io/gh/SUPERAndroidAnalyzer/abxml-rs
+[status_badge]: https://travis-ci.org/SUPERAndroidAnalyzer/abxml-rs.svg?branch=master
+[status_link]: https://travis-ci.org/SUPERAndroidAnalyzer/abxml-rs
diff --git a/examples/converter.rs b/examples/converter.rs
index cf129238f..9f2747d0f 100644
--- a/examples/converter.rs
+++ b/examples/converter.rs
@@ -1,33 +1,30 @@
 extern crate abxml;
-extern crate error_chain;
 extern crate byteorder;
-extern crate zip;
-extern crate log;
 extern crate env_logger;
+#[macro_use]
+extern crate failure;
+extern crate log;
+extern crate zip;
 
 use std::env;
-use abxml::encoder::Xml;
 use std::io::prelude::*;
-use abxml::errors::*;
-use abxml::visitor::*;
 use std::io::Cursor;
 
+use failure::{Error, ResultExt};
+
+use abxml::encoder::Xml;
+use abxml::visitor::*;
+
 fn main() {
     env_logger::try_init().unwrap();
 
     if let Err(ref e) = run() {
         println!("error: {}", e);
 
-        for e in e.iter().skip(1) {
+        for e in e.causes() {
             println!("caused by: {}", e);
         }
 
-        // The backtrace is not always generated. Try to run this example
-        // with `RUST_BACKTRACE=1`.
-        if let Some(backtrace) = e.backtrace() {
-            println!("backtrace: {:?}", backtrace);
-        }
-
         ::std::process::exit(1);
     }
 }
@@ -35,7 +32,7 @@ fn main() {
 // Most functions will return the `Result` type, imported from the
 // `errors` module. It is a typedef of the standard `Result` type
 // for which the error type is always our own `Error`.
-fn run() -> Result<()> {
+fn run() -> Result<(), Error> {
     let apk_path = match env::args().nth(1) {
         Some(path) => path,
         None => {
@@ -60,9 +57,10 @@ fn run() -> Result<()> {
     let mut archive = zip::ZipArchive::new(file).unwrap();
 
     let mut resources_content = Vec::new();
-    archive.by_name("resources.arsc").unwrap().read_to_end(
-        &mut resources_content,
-    )?;
+    archive
+        .by_name("resources.arsc")
+        .unwrap()
+        .read_to_end(&mut resources_content)?;
 
     let mut resources_visitor = ModelVisitor::default();
     Executor::arsc(&resources_content, &mut resources_visitor)?;
@@ -79,9 +77,8 @@ fn run() -> Result<()> {
                 let new_content = xml_content.clone();
 
                 let resources = resources_visitor.get_resources();
-                let out = parse_xml(&new_content, resources).chain_err(
-                    || "Could not decode target file",
-                )?;
+                let out =
+                    parse_xml(&new_content, resources).context("could not decode target file")?;
                 println!("{}", out);
             }
         }
@@ -90,29 +87,27 @@ fn run() -> Result<()> {
     Ok(())
 }
 
-fn parse_xml<'a>(content: &[u8], resources: &'a Resources<'a>) -> Result<String> {
+fn parse_xml<'a>(content: &[u8], resources: &'a Resources<'a>) -> Result<String, Error> {
     let cursor = Cursor::new(content);
     let mut visitor = XmlVisitor::new(resources);
 
     Executor::xml(cursor, &mut visitor)?;
 
     match *visitor.get_root() {
-        Some(ref root) => {
-            match *visitor.get_string_table() {
-                Some(_) => {
-                    return Xml::encode(visitor.get_namespaces(), root).chain_err(
-                        || "Could note encode XML",
-                    );
-                }
-                None => {
-                    println!("No string table found");
-                }
+        Some(ref root) => match *visitor.get_string_table() {
+            Some(_) => {
+                let res =
+                    Xml::encode(visitor.get_namespaces(), root).context("could note encode XML")?;
+                return Ok(res);
             }
-        }
+            None => {
+                println!("No string table found");
+            }
+        },
         None => {
             println!("No root on target XML");
         }
     }
 
-    Err("Could not decode XML".into())
+    bail!("could not decode XML")
 }
diff --git a/examples/exporter.rs b/examples/exporter.rs
index 5cf163da9..00f6be77a 100644
--- a/examples/exporter.rs
+++ b/examples/exporter.rs
@@ -1,13 +1,15 @@
 extern crate abxml;
-extern crate error_chain;
 extern crate byteorder;
-extern crate zip;
-extern crate log;
 extern crate env_logger;
+extern crate failure;
+extern crate log;
+extern crate zip;
 
 use std::env;
-use abxml::errors::*;
 use std::path::Path;
+
+use failure::{Error, ResultExt};
+
 use abxml::apk::Apk;
 
 fn main() {
@@ -16,16 +18,10 @@ fn main() {
     if let Err(ref e) = run() {
         println!("error: {}", e);
 
-        for e in e.iter().skip(1) {
+        for e in e.causes() {
             println!("caused by: {}", e);
         }
 
-        // The backtrace is not always generated. Try to run this example
-        // with `RUST_BACKTRACE=1`.
-        if let Some(backtrace) = e.backtrace() {
-            println!("backtrace: {:?}", backtrace);
-        }
-
         ::std::process::exit(1);
     }
 }
@@ -33,7 +29,7 @@ fn main() {
 // Most functions will return the `Result` type, imported from the
 // `errors` module. It is a typedef of the standard `Result` type
 // for which the error type is always our own `Error`.
-fn run() -> Result<()> {
+fn run() -> Result<(), Error> {
     let apk_path = match env::args().nth(1) {
         Some(path) => path,
         None => {
@@ -51,10 +47,9 @@ fn run() -> Result<()> {
     };
 
     let path = Path::new(&apk_path);
-    let mut apk = Apk::new(path).chain_err(|| "Error loading APK")?;
-    apk.export(Path::new(&output), true).chain_err(
-        || "APK could not be exported",
-    )?;
+    let mut apk = Apk::new(path).context("error loading APK")?;
+    apk.export(Path::new(&output), true)
+        .context("APK could not be exported")?;
 
     Ok(())
 }
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index 2eadd586a..2aea765ea 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -17,10 +17,6 @@ git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
 [workspace]
 members = ["."]
 
-[[bin]]
-name = "fuzzer_script_1"
-path = "fuzzers/fuzzer_script_1.rs"
-
 [[bin]]
 name = "string_table"
 path = "fuzzers/string_table.rs"
diff --git a/fuzz/fuzzers/package.rs b/fuzz/fuzzers/package.rs
index ad2b05365..10dbccae5 100644
--- a/fuzz/fuzzers/package.rs
+++ b/fuzz/fuzzers/package.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::PackageWrapper;
 
diff --git a/fuzz/fuzzers/resources.rs b/fuzz/fuzzers/resources.rs
index 6a4052952..765cd4f7c 100644
--- a/fuzz/fuzzers/resources.rs
+++ b/fuzz/fuzzers/resources.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::ResourceWrapper;
 
diff --git a/fuzz/fuzzers/string_table.rs b/fuzz/fuzzers/string_table.rs
index 85e27e08c..c54cf5e6a 100644
--- a/fuzz/fuzzers/string_table.rs
+++ b/fuzz/fuzzers/string_table.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::StringTableWrapper;
 use abxml::model::StringTable;
@@ -12,5 +13,4 @@ fuzz_target!(|data: &[u8]| {
     st.get_strings_len();
     st.get_styles_len();
     st.get_string(3984895); // TODO: Change by random number from `rand` crate
-
-});
\ No newline at end of file
+});
diff --git a/fuzz/fuzzers/table_type.rs b/fuzz/fuzzers/table_type.rs
index 519529983..ae0fbe781 100644
--- a/fuzz/fuzzers/table_type.rs
+++ b/fuzz/fuzzers/table_type.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::TableTypeWrapper;
 use abxml::model::TableType;
diff --git a/fuzz/fuzzers/table_type_spec.rs b/fuzz/fuzzers/table_type_spec.rs
index 04dca3171..24acffd1c 100644
--- a/fuzz/fuzzers/table_type_spec.rs
+++ b/fuzz/fuzzers/table_type_spec.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::TypeSpecWrapper;
 use abxml::model::TypeSpec;
diff --git a/fuzz/fuzzers/xml_namespace_end.rs b/fuzz/fuzzers/xml_namespace_end.rs
index ecd380207..b3d54fa7a 100644
--- a/fuzz/fuzzers/xml_namespace_end.rs
+++ b/fuzz/fuzzers/xml_namespace_end.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::XmlNamespaceEndWrapper;
 use abxml::model::NamespaceEnd;
@@ -11,4 +12,4 @@ fuzz_target!(|data: &[u8]| {
     xnew.get_prefix_index();
     xnew.get_namespace_index();
     xnew.get_line();
-});
\ No newline at end of file
+});
diff --git a/fuzz/fuzzers/xml_namespace_start.rs b/fuzz/fuzzers/xml_namespace_start.rs
index 6339f5b27..cdcc24ac9 100644
--- a/fuzz/fuzzers/xml_namespace_start.rs
+++ b/fuzz/fuzzers/xml_namespace_start.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::XmlNamespaceStartWrapper;
 use abxml::model::NamespaceStart;
diff --git a/fuzz/fuzzers/xml_tag_end.rs b/fuzz/fuzzers/xml_tag_end.rs
index 127087deb..2943bf173 100644
--- a/fuzz/fuzzers/xml_tag_end.rs
+++ b/fuzz/fuzzers/xml_tag_end.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::XmlTagEndWrapper;
 use abxml::model::TagEnd;
diff --git a/fuzz/fuzzers/xml_tag_start.rs b/fuzz/fuzzers/xml_tag_start.rs
index d02963d7e..1b52ee408 100644
--- a/fuzz/fuzzers/xml_tag_start.rs
+++ b/fuzz/fuzzers/xml_tag_start.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::XmlTagStartWrapper;
 use abxml::model::TagStart;
diff --git a/fuzz/fuzzers/xml_text.rs b/fuzz/fuzzers/xml_text.rs
index 01188fdaf..671d025e9 100644
--- a/fuzz/fuzzers/xml_text.rs
+++ b/fuzz/fuzzers/xml_text.rs
@@ -1,6 +1,7 @@
 #![no_main]
-#[macro_use] extern crate libfuzzer_sys;
 extern crate abxml;
+#[macro_use]
+extern crate libfuzzer_sys;
 
 use abxml::chunks::XmlTextWrapper;
 
diff --git a/src/apk.rs b/src/apk.rs
index 7587cb3f9..615084b08 100644
--- a/src/apk.rs
+++ b/src/apk.rs
@@ -1,56 +1,50 @@
 //! High level abstraction to easy the extraction to file system of APKs
 
-use zip::read::ZipArchive;
 use std::fs;
-use std;
+use std::io::{Read, Write};
 use std::path::Path;
-use std::io::Write;
-use std::io::Read;
-use errors::*;
+
+use failure::{Error, ResultExt};
+use zip::read::ZipArchive;
+
 use decoder::*;
 
 pub struct Apk {
-    handler: ZipArchive<std::fs::File>,
+    handler: ZipArchive<fs::File>,
     decoder: BufferedDecoder,
 }
 
 impl Apk {
-    pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
+    pub fn new<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
         let mut buffer = Vec::new();
-        let file = std::fs::File::open(&path)?;
+        let file = fs::File::open(&path)?;
         let mut zip_handler = ZipArchive::new(file)?;
         zip_handler
             .by_name("resources.arsc")?
             .read_to_end(&mut buffer)?;
 
-        let apk = Apk {
+        Ok(Self {
             handler: zip_handler,
             decoder: buffer.into(),
-        };
-
-        Ok(apk)
+        })
     }
 
     /// It exports to target output_path the contents of the APK, transcoding the binary XML files
     /// found on it.
-    pub fn export<P: AsRef<Path>>(&mut self, output_path: P, force: bool) -> Result<()> {
+    pub fn export<P: AsRef<Path>>(&mut self, output_path: P, force: bool) -> Result<(), Error> {
         let decoder = self.decoder
             .get_decoder()
-            .chain_err(|| "Could not get the decoder")?;
+            .context("could not get the decoder")?;
 
         if fs::create_dir_all(&output_path).is_err() && force {
-            fs::remove_dir_all(&output_path).chain_err(|| {
-                format!(
-                    "Could not clean target directory: {}",
-                    output_path.as_ref().display()
-                )
-            })?;
-            fs::create_dir_all(&output_path).chain_err(|| {
-                format!(
-                    "Error creating the output folder: {}",
-                    output_path.as_ref().display()
-                )
-            })?;
+            fs::remove_dir_all(&output_path).context(format_err!(
+                "could not clean target directory: {}",
+                output_path.as_ref().display()
+            ))?;
+            fs::create_dir_all(&output_path).context(format_err!(
+                "error creating the output folder: {}",
+                output_path.as_ref().display()
+            ))?;
         }
 
         // Iterate over all the files on the ZIP and extract them
@@ -58,11 +52,11 @@ impl Apk {
             let (file_name, contents) = {
                 let mut current_file = self.handler
                     .by_index(i)
-                    .chain_err(|| "Could not read ZIP entry")?;
+                    .context("could not read ZIP entry")?;
                 let mut contents = Vec::new();
                 current_file
                     .read_to_end(&mut contents)
-                    .chain_err(|| format!("Could not read: {}", current_file.name()))?;
+                    .context(format!("could not read: {}", current_file.name()))?;
                 let is_xml = current_file.name().to_string();
 
                 (is_xml, contents)
@@ -81,7 +75,7 @@ impl Apk {
             };
 
             Self::write_file(&output_path, &file_name, &contents)
-                .chain_err(|| "Could not write output file")?;
+                .context("could not write output file")?;
         }
         Ok(())
     }
@@ -90,21 +84,20 @@ impl Apk {
         base_path: B,
         relative: R,
         content: &[u8],
-    ) -> Result<()> {
+    ) -> Result<(), Error> {
         let full_path = base_path.as_ref().join(&relative);
         // println!("Full path: {}", full_path.display());
-        fs::create_dir_all(full_path.parent().unwrap())
-            .chain_err(|| "Could not create the output dir")?;
+        fs::create_dir_all(full_path.parent().unwrap()).context("could not create the output dir")?;
 
         let mut descriptor = fs::OpenOptions::new()
             .write(true)
             .create_new(true)
             .open(full_path)
-            .chain_err(|| "Could not open file to write")?;
+            .context("could not open file to write")?;
 
         descriptor
             .write_all(content)
-            .chain_err(|| "Could not write to target file")?;
+            .context("could not write to target file")?;
 
         Ok(())
     }
diff --git a/src/chunks/chunk_header.rs b/src/chunks/chunk_header.rs
index 2116709aa..622d5a31a 100644
--- a/src/chunks/chunk_header.rs
+++ b/src/chunks/chunk_header.rs
@@ -10,11 +10,11 @@ pub struct ChunkHeader {
 
 impl ChunkHeader {
     pub fn new(offset: u64, header_size: u16, chunk_size: u32, chunk_type: u16) -> Self {
-        ChunkHeader {
-            offset: offset,
-            header_size: header_size,
-            chunk_size: chunk_size,
-            chunk_type: chunk_type,
+        Self {
+            offset,
+            header_size,
+            chunk_size,
+            chunk_type,
         }
     }
 
diff --git a/src/chunks/mod.rs b/src/chunks/mod.rs
index 9c43f2296..283d59638 100644
--- a/src/chunks/mod.rs
+++ b/src/chunks/mod.rs
@@ -1,31 +1,25 @@
 //! Structs to represent chunks and iterate them
 use std::io::Cursor;
+
 use byteorder::{LittleEndian, ReadBytesExt};
+use failure::Error;
 
-pub mod string_table;
 mod chunk_header;
 mod package;
-pub mod table_type;
 mod resource;
+pub mod string_table;
+pub mod table_type;
 mod table_type_spec;
 mod xml;
 
-pub use self::string_table::StringTableWrapper;
-pub use self::string_table::StringTableCache;
 pub use self::chunk_header::ChunkHeader;
 pub use self::package::PackageWrapper;
-pub use self::table_type_spec::TypeSpecWrapper;
-pub use self::table_type::TableTypeWrapper;
-pub use self::table_type::ConfigurationWrapper;
-
 pub use self::resource::ResourceWrapper;
-pub use self::xml::XmlNamespaceStartWrapper;
-pub use self::xml::XmlNamespaceEndWrapper;
-pub use self::xml::XmlTagStartWrapper;
-pub use self::xml::XmlTagEndWrapper;
-pub use self::xml::XmlTextWrapper;
-
-use errors::*;
+pub use self::string_table::{StringTableCache, StringTableWrapper};
+pub use self::table_type::{ConfigurationWrapper, TableTypeWrapper};
+pub use self::table_type_spec::TypeSpecWrapper;
+pub use self::xml::{XmlNamespaceEndWrapper, XmlNamespaceStartWrapper, XmlTagEndWrapper,
+                    XmlTagStartWrapper, XmlTextWrapper};
 
 pub const TOKEN_STRING_TABLE: u16 = 0x0001;
 pub const TOKEN_RESOURCE: u16 = 0x0180;
@@ -59,13 +53,13 @@ pub struct ChunkLoaderStream<'a> {
 
 impl<'a> ChunkLoaderStream<'a> {
     pub fn new(cursor: Cursor<&'a [u8]>) -> Self {
-        ChunkLoaderStream {
-            cursor: cursor,
+        Self {
+            cursor,
             previous: None,
         }
     }
 
-    fn read_one(&mut self) -> Result<Chunk<'a>> {
+    fn read_one(&mut self) -> Result<Chunk<'a>, Error> {
         let initial_position = self.cursor.position();
         let token = self.cursor.read_u16::<LittleEndian>()?;
         let header_size = self.cursor.read_u16::<LittleEndian>()?;
@@ -115,9 +109,9 @@ impl<'a> ChunkLoaderStream<'a> {
 }
 
 impl<'a> Iterator for ChunkLoaderStream<'a> {
-    type Item = Result<Chunk<'a>>;
+    type Item = Result<Chunk<'a>, Error>;
 
-    fn next(&mut self) -> Option<Result<Chunk<'a>>> {
+    fn next(&mut self) -> Option<Result<Chunk<'a>, Error>> {
         if let Some(prev) = self.previous {
             if prev == self.cursor.position() {
                 return None;
@@ -138,8 +132,8 @@ impl<'a> Iterator for ChunkLoaderStream<'a> {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::io::Cursor;
     use model::owned::{OwnedBuf, ResourcesBuf, StringTableBuf};
+    use std::io::Cursor;
 
     #[test]
     fn it_can_detect_loops() {
diff --git a/src/chunks/package.rs b/src/chunks/package.rs
index 7c908f421..70aabafa1 100644
--- a/src/chunks/package.rs
+++ b/src/chunks/package.rs
@@ -1,34 +1,41 @@
 use std::io::Cursor;
+
 use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
 use encoding::codec::utf_16;
 use encoding::codec::utf_16::Little;
+use failure::Error;
 
 pub struct PackageWrapper<'a> {
     raw_data: &'a [u8],
 }
 
 impl<'a> PackageWrapper<'a> {
-    pub fn new(slice: &'a [u8]) -> Self {
-        PackageWrapper { raw_data: slice }
+    pub fn new(raw_data: &'a [u8]) -> Self {
+        Self { raw_data }
     }
 
-    pub fn get_id(&self) -> Result<u32> {
+    pub fn get_id(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    pub fn get_name(&self) -> Result<String> {
+    pub fn get_name(&self) -> Result<String, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(12);
         let initial_position = cursor.position();
+        ensure!(
+            ((initial_position + 256) as usize) < self.raw_data.len(),
+            "cursor position out of bounds"
+        );
+
         let final_position = self.find_end_position(initial_position as usize);
 
-        if self.raw_data.len() < (initial_position + 256) as usize {
-            return Err("Not enough bytes to retrieve package name".into());
-        }
+        ensure!(
+            self.raw_data.len() >= (initial_position + 256) as usize,
+            "not enough bytes to retrieve package name"
+        );
 
         let raw_str = &cursor.get_ref()[initial_position as usize..final_position];
         let mut decoder = utf_16::UTF16Decoder::<Little>::new();
@@ -38,7 +45,7 @@ impl<'a> PackageWrapper<'a> {
 
         match decode_error {
             None => Ok(o),
-            Some(_) => Err("Error decoding UTF8 string".into()),
+            Some(_) => Err(format_err!("error decoding UTF8 string")),
         }
     }
 
diff --git a/src/chunks/resource.rs b/src/chunks/resource.rs
index 0fdbdff64..3bc591c49 100644
--- a/src/chunks/resource.rs
+++ b/src/chunks/resource.rs
@@ -1,6 +1,8 @@
 use std::io::Cursor;
+
 use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
+use failure::Error;
+
 use model::owned::ResourcesBuf;
 
 #[allow(dead_code)]
@@ -10,24 +12,22 @@ pub struct ResourceWrapper<'a> {
 
 impl<'a> ResourceWrapper<'a> {
     pub fn new(raw_data: &'a [u8]) -> Self {
-        ResourceWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
-    pub fn get_resources(&self) -> Result<Vec<u32>> {
+    pub fn get_resources(&self) -> Result<Vec<u32>, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(4);
 
         let count = cursor.read_u32::<LittleEndian>()?;
         let amount_of_resources = (count / 4) - 2;
 
-        if count > self.raw_data.len() as u32 {
-            return Err(format!(
-                "There is not enough data on the buffer ({}) to read \
-                 the reported resources count ({})",
-                self.raw_data.len(),
-                count
-            ).into());
-        }
+        ensure!(
+            count <= self.raw_data.len() as u32,
+            "there is not enough data on the buffer ({}) to read the reported resources count ({})",
+            self.raw_data.len(),
+            count
+        );
 
         let mut resources = Vec::with_capacity(amount_of_resources as usize);
 
@@ -38,7 +38,7 @@ impl<'a> ResourceWrapper<'a> {
         Ok(resources)
     }
 
-    pub fn to_buffer(&self) -> Result<ResourcesBuf> {
+    pub fn to_buffer(&self) -> Result<ResourcesBuf, Error> {
         let mut owned = ResourcesBuf::default();
 
         for r in &self.get_resources()? {
@@ -52,8 +52,8 @@ impl<'a> ResourceWrapper<'a> {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use model::owned::ResourcesBuf;
     use model::owned::OwnedBuf;
+    use model::owned::ResourcesBuf;
 
     #[test]
     fn it_can_not_decode_a_buffer_with_an_invalid_size() {
@@ -69,8 +69,8 @@ mod tests {
         let result = wrapper.get_resources();
         assert!(result.is_err());
         assert_eq!(
-            "There is not enough data on the buffer (16) to read the \
-             reported resources count (255)",
+            "there is not enough data on the buffer (16) to read the reported resources count \
+             (255)",
             result.err().unwrap().to_string()
         );
     }
diff --git a/src/chunks/string_table.rs b/src/chunks/string_table.rs
index a3a1a5d02..8a49072f7 100644
--- a/src/chunks/string_table.rs
+++ b/src/chunks/string_table.rs
@@ -1,21 +1,23 @@
+use std::cell::RefCell;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
+use std::collections::HashMap;
 use std::io::Cursor;
-use byteorder::{LittleEndian, ReadBytesExt};
 use std::rc::Rc;
-use errors::*;
-use model::StringTable;
+
+use byteorder::{LittleEndian, ReadBytesExt};
 use encoding::codec::{utf_16, utf_8};
+use failure::Error;
+
 use model::owned::{Encoding as EncodingType, StringTableBuf};
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
+use model::StringTable;
 
 pub struct StringTableWrapper<'a> {
     raw_data: &'a [u8],
 }
 
 impl<'a> StringTableWrapper<'a> {
-    pub fn new(slice: &'a [u8]) -> Self {
-        StringTableWrapper { raw_data: slice }
+    pub fn new(raw_data: &'a [u8]) -> Self {
+        Self { raw_data }
     }
 
     pub fn get_flags(&self) -> u32 {
@@ -25,7 +27,7 @@ impl<'a> StringTableWrapper<'a> {
         cursor.read_u32::<LittleEndian>().unwrap_or(0)
     }
 
-    pub fn to_buffer(&self) -> Result<StringTableBuf> {
+    pub fn to_buffer(&self) -> Result<StringTableBuf, Error> {
         let mut owned = StringTableBuf::default();
 
         if !self.is_utf8() {
@@ -40,7 +42,7 @@ impl<'a> StringTableWrapper<'a> {
         Ok(owned)
     }
 
-    fn get_string_position(&self, idx: u32) -> Result<u64> {
+    fn get_string_position(&self, idx: u32) -> Result<u64, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(20);
         let str_offset = cursor.read_u32::<LittleEndian>()?;
@@ -62,7 +64,7 @@ impl<'a> StringTableWrapper<'a> {
         Ok(position as u64)
     }
 
-    fn parse_string(&self, offset: u32) -> Result<String> {
+    fn parse_string(&self, offset: u32) -> Result<String, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(offset as u64);
 
@@ -99,9 +101,10 @@ impl<'a> StringTableWrapper<'a> {
             let a = ini_offset;
             let b = ini_offset + length;
 
-            if a > self.raw_data.len() as u32 || b > self.raw_data.len() as u32 || a > b {
-                return Err("Sub-slice out of raw_data range".into());
-            }
+            ensure!(
+                a <= self.raw_data.len() as u32 && b <= self.raw_data.len() as u32 && a <= b,
+                "sub-slice out of raw_data range"
+            );
 
             let subslice: &[u8] = &self.raw_data[a as usize..b as usize];
 
@@ -112,7 +115,7 @@ impl<'a> StringTableWrapper<'a> {
 
             match decode_error {
                 None => Ok(o),
-                Some(_) => Err("Error decoding UTF8 string".into()),
+                Some(_) => Err(format_err!("error decoding UTF8 string")),
             }
         } else {
             let size1 = cursor.read_u8()? as u32;
@@ -123,9 +126,10 @@ impl<'a> StringTableWrapper<'a> {
             let a = offset + 2;
             let b = offset + 2 + (val * 2);
 
-            if a > self.raw_data.len() as u32 || b > self.raw_data.len() as u32 || a > b {
-                return Err("Sub-slice out of raw_data range".into());
-            }
+            ensure!(
+                a <= self.raw_data.len() as u32 && b <= self.raw_data.len() as u32 && a <= b,
+                "sub-slice out of raw_data range"
+            );
 
             let subslice: &[u8] = &self.raw_data[a as usize..b as usize];
 
@@ -136,7 +140,7 @@ impl<'a> StringTableWrapper<'a> {
 
             match decode_error {
                 None => Ok(o),
-                Some(_) => Err("Error decoding UTF16 string".into()),
+                Some(_) => Err(format_err!("error decoding UTF16 string")),
             }
         }
     }
@@ -161,10 +165,8 @@ impl<'a> StringTable for StringTableWrapper<'a> {
         cursor.read_u32::<LittleEndian>().unwrap_or(0)
     }
 
-    fn get_string(&self, idx: u32) -> Result<Rc<String>> {
-        if idx > self.get_strings_len() {
-            return Err("Index out of bounds".into());
-        }
+    fn get_string(&self, idx: u32) -> Result<Rc<String>, Error> {
+        ensure!(idx <= self.get_strings_len(), "index out of bounds");
 
         let string = self.get_string_position(idx)
             .and_then(|position| self.parse_string(position as u32))?;
@@ -180,8 +182,8 @@ pub struct StringTableCache<S: StringTable> {
 
 impl<S: StringTable> StringTableCache<S> {
     pub fn new(inner: S) -> Self {
-        StringTableCache {
-            inner: inner,
+        Self {
+            inner,
             cache: RefCell::new(HashMap::new()),
         }
     }
@@ -196,7 +198,7 @@ impl<S: StringTable> StringTable for StringTableCache<S> {
         self.inner.get_styles_len()
     }
 
-    fn get_string(&self, idx: u32) -> Result<Rc<String>> {
+    fn get_string(&self, idx: u32) -> Result<Rc<String>, Error> {
         let mut cache = self.cache.borrow_mut();
         let entry = cache.entry(idx);
 
diff --git a/src/chunks/table_type/configuration.rs b/src/chunks/table_type/configuration.rs
index 78e8675f1..cba6ac237 100644
--- a/src/chunks/table_type/configuration.rs
+++ b/src/chunks/table_type/configuration.rs
@@ -1,9 +1,11 @@
 use std::io::Cursor;
-use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
-use model::Configuration;
 use std::string::ToString;
+
+use byteorder::{LittleEndian, ReadBytesExt};
+use failure::Error;
+
 use model::owned::ConfigurationBuf;
+use model::Configuration;
 
 pub struct ConfigurationWrapper<'a> {
     slice: &'a [u8],
@@ -11,37 +13,37 @@ pub struct ConfigurationWrapper<'a> {
 
 impl<'a> ConfigurationWrapper<'a> {
     pub fn new(slice: &'a [u8]) -> Self {
-        ConfigurationWrapper { slice: slice }
+        Self { slice }
     }
 
-    pub fn to_buffer(&self) -> Result<ConfigurationBuf> {
+    pub fn to_buffer(&self) -> Result<ConfigurationBuf, Error> {
         ConfigurationBuf::from_cursor(self.slice.into())
     }
 }
 
 impl<'a> Configuration for ConfigurationWrapper<'a> {
-    fn get_size(&self) -> Result<u32> {
+    fn get_size(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(0);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    fn get_mcc(&self) -> Result<u16> {
+    fn get_mcc(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(4);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_mnc(&self) -> Result<u16> {
+    fn get_mnc(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(6);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_language(&self) -> Result<String> {
+    fn get_language(&self) -> Result<String, Error> {
         let lang_low = self.slice[8];
         let lang_high = self.slice[9];
 
@@ -50,7 +52,7 @@ impl<'a> Configuration for ConfigurationWrapper<'a> {
         Ok(region.to_string())
     }
 
-    fn get_region(&self) -> Result<String> {
+    fn get_region(&self) -> Result<String, Error> {
         let lang_low = self.slice[10];
         let lang_high = self.slice[11];
 
@@ -59,130 +61,115 @@ impl<'a> Configuration for ConfigurationWrapper<'a> {
         Ok(region.to_string())
     }
 
-    fn get_orientation(&self) -> Result<u8> {
+    fn get_orientation(&self) -> Result<u8, Error> {
         Ok(self.slice[12])
     }
 
-    fn get_touchscreen(&self) -> Result<u8> {
+    fn get_touchscreen(&self) -> Result<u8, Error> {
         Ok(self.slice[13])
     }
 
-    fn get_density(&self) -> Result<u16> {
+    fn get_density(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(14);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_keyboard(&self) -> Result<u8> {
+    fn get_keyboard(&self) -> Result<u8, Error> {
         Ok(self.slice[16])
     }
 
-    fn get_navigation(&self) -> Result<u8> {
+    fn get_navigation(&self) -> Result<u8, Error> {
         Ok(self.slice[17])
     }
 
-    fn get_input_flags(&self) -> Result<u8> {
+    fn get_input_flags(&self) -> Result<u8, Error> {
         Ok(self.slice[18])
     }
 
-    fn get_width(&self) -> Result<u16> {
+    fn get_width(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(20);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_height(&self) -> Result<u16> {
+    fn get_height(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(22);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_sdk_version(&self) -> Result<u16> {
+    fn get_sdk_version(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(24);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_min_sdk_version(&self) -> Result<u16> {
+    fn get_min_sdk_version(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(26);
 
         Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_screen_layout(&self) -> Result<u8> {
+    fn get_screen_layout(&self) -> Result<u8, Error> {
         let size = self.get_size()?;
+        ensure!(size >= 28, "not enough bytes to retrieve the field");
 
-        if size >= 28 {
-            Ok(self.slice[28])
-        } else {
-            Err("Not enough bytes to retrieve the field".into())
-        }
+        Ok(self.slice[28])
     }
 
-    fn get_ui_mode(&self) -> Result<u8> {
+    fn get_ui_mode(&self) -> Result<u8, Error> {
         let size = self.get_size()?;
+        ensure!(size >= 29, "not enough bytes to retrieve the field");
 
-        if size >= 29 {
-            Ok(self.slice[29])
-        } else {
-            Err("Not enough bytes to retrieve the field".into())
-        }
+        Ok(self.slice[29])
     }
 
-    fn get_smallest_screen(&self) -> Result<u16> {
+    fn get_smallest_screen(&self) -> Result<u16, Error> {
         let size = self.get_size()?;
+        ensure!(size >= 30, "not enough bytes to retrieve the field");
 
-        if size >= 30 {
-            let mut cursor = Cursor::new(self.slice);
-            cursor.set_position(30);
+        let mut cursor = Cursor::new(self.slice);
+        cursor.set_position(30);
 
-            Ok(cursor.read_u16::<LittleEndian>()?)
-        } else {
-            Err("Not enough bytes to retrieve the field".into())
-        }
+        Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_screen_width(&self) -> Result<u16> {
+    fn get_screen_width(&self) -> Result<u16, Error> {
         let size = self.get_size()?;
+        ensure!(size >= 32, "not enough bytes to retrieve the field");
 
-        if size >= 32 {
-            let mut cursor = Cursor::new(self.slice);
-            cursor.set_position(32);
+        let mut cursor = Cursor::new(self.slice);
+        cursor.set_position(32);
 
-            Ok(cursor.read_u16::<LittleEndian>()?)
-        } else {
-            Err("Not enough bytes to retrieve the field".into())
-        }
+        Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_screen_height(&self) -> Result<u16> {
+    fn get_screen_height(&self) -> Result<u16, Error> {
         let size = self.get_size()?;
+        ensure!(size >= 34, "not enough bytes to retrieve the field");
 
-        if size >= 34 {
-            let mut cursor = Cursor::new(self.slice);
-            cursor.set_position(34);
+        let mut cursor = Cursor::new(self.slice);
+        cursor.set_position(34);
 
-            Ok(cursor.read_u16::<LittleEndian>()?)
-        } else {
-            Err("Not enough bytes to retrieve the field".into())
-        }
+        Ok(cursor.read_u16::<LittleEndian>()?)
     }
 
-    fn get_locale_script(&self) -> Result<Option<String>> {
-        Err("Not enough bytes to retrieve the field".into())
+    fn get_locale_script(&self) -> Result<Option<String>, Error> {
+        bail!("not enough bytes to retrieve the field")
     }
 
-    fn get_locale_variant(&self) -> Result<Option<String>> {
-        Err("Not enough bytes to retrieve the field".into())
+    fn get_locale_variant(&self) -> Result<Option<String>, Error> {
+        bail!("not enough bytes to retrieve the field")
     }
 
-    fn get_secondary_layout(&self) -> Result<Option<u8>> {
-        Err("Not enough bytes to retrieve the field".into())
+    fn get_secondary_layout(&self) -> Result<Option<u8>, Error> {
+        bail!("not enough bytes to retrieve the field")
     }
 }
 
@@ -200,10 +187,10 @@ impl Into<(u8, u8)> for Region {
 impl<'a> From<&'a [u8]> for Region {
     fn from(input: &'a [u8]) -> Self {
         if input.len() != 2 {
-            Region { low: 0, high: 0 }
+            Self { low: 0, high: 0 }
         } else {
             let input_ref: &[u8] = input.as_ref();
-            Region {
+            Self {
                 low: input_ref[0],
                 high: input_ref[1],
             }
@@ -213,7 +200,7 @@ impl<'a> From<&'a [u8]> for Region {
 
 impl From<(u8, u8)> for Region {
     fn from(input: (u8, u8)) -> Self {
-        Region {
+        Self {
             low: input.0,
             high: input.1,
         }
@@ -225,7 +212,7 @@ impl ToString for Region {
         let mut chrs = Vec::new();
 
         if self.low == 0 && self.high == 0 {
-            return "any".to_string();
+            return "any".to_owned();
         }
 
         chrs.push(self.low);
diff --git a/src/chunks/table_type/mod.rs b/src/chunks/table_type/mod.rs
index b352f9f60..200f3d720 100644
--- a/src/chunks/table_type/mod.rs
+++ b/src/chunks/table_type/mod.rs
@@ -1,9 +1,10 @@
 use std::io::Cursor;
+
 use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
+use failure::Error;
+
+use model::owned::{ComplexEntry, Entry, EntryHeader, SimpleEntry, TableTypeBuf};
 use model::TableType;
-use model::owned::TableTypeBuf;
-use model::owned::{ComplexEntry, Entry, EntryHeader, SimpleEntry};
 
 pub use self::configuration::ConfigurationWrapper;
 pub use self::configuration::Region;
@@ -16,14 +17,14 @@ pub struct TableTypeWrapper<'a> {
 }
 
 impl<'a> TableTypeWrapper<'a> {
-    pub fn new(slice: &'a [u8], data_offset: u64) -> Self {
-        TableTypeWrapper {
-            raw_data: slice,
-            data_offset: data_offset,
+    pub fn new(raw_data: &'a [u8], data_offset: u64) -> Self {
+        Self {
+            raw_data,
+            data_offset,
         }
     }
 
-    pub fn to_buffer(&self) -> Result<TableTypeBuf> {
+    pub fn to_buffer(&self) -> Result<TableTypeBuf, Error> {
         let id = self.get_id()?;
         let amount = self.get_amount()?;
         let config = self.get_configuration()?.to_buffer()?;
@@ -37,14 +38,14 @@ impl<'a> TableTypeWrapper<'a> {
         Ok(owned)
     }
 
-    pub fn get_entries(&self) -> Result<Vec<Entry>> {
+    pub fn get_entries(&self) -> Result<Vec<Entry>, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(self.data_offset);
 
         self.decode_entries(&mut cursor)
     }
 
-    fn decode_entries(&self, cursor: &mut Cursor<&[u8]>) -> Result<Vec<Entry>> {
+    fn decode_entries(&self, cursor: &mut Cursor<&[u8]>) -> Result<Vec<Entry>, Error> {
         let mut offsets = Vec::new();
         let mut entries = Vec::new();
 
@@ -74,7 +75,7 @@ impl<'a> TableTypeWrapper<'a> {
         Ok(entries)
     }
 
-    fn decode_entry(cursor: &mut Cursor<&[u8]>, id: u32) -> Result<Option<Entry>> {
+    fn decode_entry(cursor: &mut Cursor<&[u8]>, id: u32) -> Result<Option<Entry>, Error> {
         let header_size = cursor.read_u16::<LittleEndian>()?;
         let flags = cursor.read_u16::<LittleEndian>()?;
         let key_index = cursor.read_u32::<LittleEndian>()?;
@@ -91,7 +92,7 @@ impl<'a> TableTypeWrapper<'a> {
         cursor: &mut Cursor<&[u8]>,
         header: &EntryHeader,
         id: u32,
-    ) -> Result<Option<Entry>> {
+    ) -> Result<Option<Entry>, Error> {
         cursor.read_u16::<LittleEndian>()?;
         // Padding
         cursor.read_u8()?;
@@ -108,7 +109,7 @@ impl<'a> TableTypeWrapper<'a> {
         cursor: &mut Cursor<&[u8]>,
         header: &EntryHeader,
         id: u32,
-    ) -> Result<Option<Entry>> {
+    ) -> Result<Option<Entry>, Error> {
         let parent_entry = cursor.read_u32::<LittleEndian>()?;
         let value_count = cursor.read_u32::<LittleEndian>()?;
         let mut entries = Vec::with_capacity(value_count as usize);
@@ -146,7 +147,7 @@ impl<'a> TableTypeWrapper<'a> {
 impl<'a> TableType for TableTypeWrapper<'a> {
     type Configuration = ConfigurationWrapper<'a>;
 
-    fn get_id(&self) -> Result<u8> {
+    fn get_id(&self) -> Result<u8, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
         let out_value = cursor.read_u32::<LittleEndian>()? & 0xF;
@@ -154,21 +155,22 @@ impl<'a> TableType for TableTypeWrapper<'a> {
         Ok(out_value as u8)
     }
 
-    fn get_amount(&self) -> Result<u32> {
+    fn get_amount(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(12);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    fn get_configuration(&self) -> Result<Self::Configuration> {
+    fn get_configuration(&self) -> Result<Self::Configuration, Error> {
         let ini = 20 as usize;
         let end = self.data_offset as usize;
 
-        if ini > end || (end - ini) <= 28 || self.raw_data.len() < ini || self.raw_data.len() < end
-        {
-            return Err("Configuration slice is not valid".into());
-        }
+        ensure!(
+            ini <= end && (end - ini) > 28 && self.raw_data.len() >= ini
+                && self.raw_data.len() >= end,
+            "configuration slice is not valid"
+        );
 
         let slice = &self.raw_data[ini..end];
         let wrapper = ConfigurationWrapper::new(slice);
@@ -176,11 +178,11 @@ impl<'a> TableType for TableTypeWrapper<'a> {
         Ok(wrapper)
     }
 
-    fn get_entry(&self, index: u32) -> Result<Entry> {
+    fn get_entry(&self, index: u32) -> Result<Entry, Error> {
         let entries = self.get_entries()?;
         entries
             .get(index as usize)
             .cloned()
-            .ok_or_else(|| "Entry not found".into())
+            .ok_or_else(|| format_err!("entry not found"))
     }
 }
diff --git a/src/chunks/table_type_spec.rs b/src/chunks/table_type_spec.rs
index bfc35acf3..7fed2f19a 100644
--- a/src/chunks/table_type_spec.rs
+++ b/src/chunks/table_type_spec.rs
@@ -1,8 +1,10 @@
 use std::io::Cursor;
+
 use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
-use model::TypeSpec;
+use failure::Error;
+
 use model::owned::TableTypeSpecBuf;
+use model::TypeSpec;
 
 #[derive(Clone)]
 pub struct TypeSpecWrapper<'a> {
@@ -10,11 +12,11 @@ pub struct TypeSpecWrapper<'a> {
 }
 
 impl<'a> TypeSpecWrapper<'a> {
-    pub fn new(slice: &'a [u8]) -> Self {
-        TypeSpecWrapper { raw_data: slice }
+    pub fn new(raw_data: &'a [u8]) -> Self {
+        Self { raw_data }
     }
 
-    pub fn to_buffer(&self) -> Result<TableTypeSpecBuf> {
+    pub fn to_buffer(&self) -> Result<TableTypeSpecBuf, Error> {
         let mut owned = TableTypeSpecBuf::new(self.get_id()? as u16);
         let amount = self.get_amount()?;
 
@@ -27,7 +29,7 @@ impl<'a> TypeSpecWrapper<'a> {
 }
 
 impl<'a> TypeSpec for TypeSpecWrapper<'a> {
-    fn get_id(&self) -> Result<u16> {
+    fn get_id(&self) -> Result<u16, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
         let out_value = cursor.read_u32::<LittleEndian>()? & 0xFF;
@@ -35,19 +37,21 @@ impl<'a> TypeSpec for TypeSpecWrapper<'a> {
         Ok(out_value as u16)
     }
 
-    fn get_amount(&self) -> Result<u32> {
+    fn get_amount(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(12);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    fn get_flag(&self, index: u32) -> Result<u32> {
+    fn get_flag(&self, index: u32) -> Result<u32, Error> {
         let amount = self.get_amount()?;
-
-        if index >= amount {
-            return Err(format!("Invalid flag on index {} out of {}", index, amount).into());
-        }
+        ensure!(
+            index < amount,
+            "invalid flag on index {} out of {}",
+            index,
+            amount
+        );
 
         let mut cursor = Cursor::new(self.raw_data);
         let flag_offset = 16 + (index * 4) as u64;
@@ -76,7 +80,7 @@ mod tests {
         let errored_flag = wrapper.get_flag(1541);
         assert!(errored_flag.is_err());
         assert_eq!(
-            "Invalid flag on index 1541 out of 1541",
+            "invalid flag on index 1541 out of 1541",
             errored_flag.err().unwrap().to_string()
         );
     }
diff --git a/src/chunks/xml.rs b/src/chunks/xml.rs
index b97d36cf0..fc1b57af1 100644
--- a/src/chunks/xml.rs
+++ b/src/chunks/xml.rs
@@ -1,11 +1,12 @@
 use std::io::Cursor;
-use byteorder::{LittleEndian, ReadBytesExt};
 use std::rc::Rc;
-use errors::*;
-use model::StringTable;
+
+use byteorder::{LittleEndian, ReadBytesExt};
+use failure::{Error, ResultExt};
+
 use model::owned::{AttributeBuf, XmlNamespaceEndBuf, XmlNamespaceStartBuf, XmlTagEndBuf,
                    XmlTagStartBuf};
-use model::{AttributeTrait, NamespaceEnd, NamespaceStart, TagEnd, TagStart};
+use model::{AttributeTrait, NamespaceEnd, NamespaceStart, StringTable, TagEnd, TagStart};
 
 pub struct XmlNamespaceStartWrapper<'a> {
     raw_data: &'a [u8],
@@ -13,24 +14,24 @@ pub struct XmlNamespaceStartWrapper<'a> {
 
 impl<'a> XmlNamespaceStartWrapper<'a> {
     pub fn new(raw_data: &'a [u8]) -> Self {
-        XmlNamespaceStartWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
-    pub fn get_prefix_index(&self) -> Result<u32> {
+    pub fn get_prefix_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(16);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    pub fn get_namespace_index(&self) -> Result<u32> {
+    pub fn get_namespace_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(20);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    pub fn to_buffer(&self) -> Result<XmlNamespaceStartBuf> {
+    pub fn to_buffer(&self) -> Result<XmlNamespaceStartBuf, Error> {
         let namespace_start = XmlNamespaceStartBuf::new(
             self.get_line()?,
             self.get_prefix_index()?,
@@ -42,21 +43,21 @@ impl<'a> XmlNamespaceStartWrapper<'a> {
 }
 
 impl<'a> NamespaceStart for XmlNamespaceStartWrapper<'a> {
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let index = self.get_prefix_index()?;
         let string = string_table.get_string(index)?;
 
         Ok(string)
     }
 
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let index = self.get_namespace_index()?;
         let string = string_table.get_string(index)?;
 
         Ok(string)
     }
 
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
 
@@ -71,24 +72,24 @@ pub struct XmlNamespaceEndWrapper<'a> {
 
 impl<'a> XmlNamespaceEndWrapper<'a> {
     pub fn new(raw_data: &'a [u8]) -> Self {
-        XmlNamespaceEndWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
-    pub fn get_prefix_index(&self) -> Result<u32> {
+    pub fn get_prefix_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(16);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    pub fn get_namespace_index(&self) -> Result<u32> {
+    pub fn get_namespace_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(20);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    pub fn to_buffer(&self) -> Result<XmlNamespaceEndBuf> {
+    pub fn to_buffer(&self) -> Result<XmlNamespaceEndBuf, Error> {
         let namespace_end = XmlNamespaceEndBuf::new(
             self.get_line()?,
             self.get_prefix_index()?,
@@ -100,21 +101,21 @@ impl<'a> XmlNamespaceEndWrapper<'a> {
 }
 
 impl<'a> NamespaceEnd for XmlNamespaceEndWrapper<'a> {
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
 
         Ok(cursor.read_u32::<LittleEndian>()?)
     }
 
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let index = self.get_prefix_index()?;
         let string = string_table.get_string(index)?;
 
         Ok(string)
     }
 
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let index = self.get_namespace_index()?;
         let string = string_table.get_string(index)?;
 
@@ -130,77 +131,78 @@ pub struct XmlTagStartWrapper<'a> {
 impl<'a> TagStart for XmlTagStartWrapper<'a> {
     type Attribute = AttributeWrapper<'a>;
 
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(8);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get line")
+            .context("could not get line")?)
     }
 
-    fn get_field1(&self) -> Result<u32> {
+    fn get_field1(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(12);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_namespace_index(&self) -> Result<u32> {
+    fn get_namespace_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(16);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_element_name_index(&self) -> Result<u32> {
+    fn get_element_name_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(20);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_field2(&self) -> Result<u32> {
+    fn get_field2(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(24);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_attributes_amount(&self) -> Result<u32> {
+    fn get_attributes_amount(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(28);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_class(&self) -> Result<u32> {
+    fn get_class(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(32);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 
-    fn get_attribute(&self, index: u32) -> Result<Self::Attribute> {
+    fn get_attribute(&self, index: u32) -> Result<Self::Attribute, Error> {
         let offset = 36 + (index * (5 * 4)) as u64;
-        let initial_position: usize = offset as usize;
-        let final_position: usize = (offset + (5 * 4)) as usize;
+        let initial_position = offset as usize;
+        let final_position = (offset + (5 * 4)) as usize;
 
-        if self.raw_data.len() < initial_position || self.raw_data.len() < final_position {
-            return Err("Requested attribute out of bounds".into());
-        }
+        ensure!(
+            self.raw_data.len() >= final_position,
+            "requested attribute out of bounds"
+        );
 
         let slice = &self.raw_data[initial_position..final_position];
 
@@ -213,11 +215,11 @@ impl<'a> TagStart for XmlTagStartWrapper<'a> {
 impl<'a> XmlTagStartWrapper<'a> {
     /// Creates a new `XmlTagStartWrapper`
     pub fn new(raw_data: &'a [u8]) -> Self {
-        XmlTagStartWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
     /// It converts the wrapper into a `XmlTagStartBuf` which can be later manipulated
-    pub fn to_buffer(&self) -> Result<XmlTagStartBuf> {
+    pub fn to_buffer(&self) -> Result<XmlTagStartBuf, Error> {
         let mut tag_start = XmlTagStartBuf::new(
             self.get_line()?,
             self.get_field1()?,
@@ -228,8 +230,7 @@ impl<'a> XmlTagStartWrapper<'a> {
         );
 
         for i in 0..self.get_attributes_amount()? {
-            let attr = self.get_attribute(i)
-                .chain_err(|| "Could not get attribute")?;
+            let attr = self.get_attribute(i).context("could not get attribute")?;
             tag_start.add_attribute(attr.to_buffer()?);
         }
 
@@ -243,60 +244,60 @@ pub struct AttributeWrapper<'a> {
 }
 
 impl<'a> AttributeTrait for AttributeWrapper<'a> {
-    fn get_namespace(&self) -> Result<u32> {
+    fn get_namespace(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(0);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get namespace")
+            .context("could not get namespace")?)
     }
 
-    fn get_name(&self) -> Result<u32> {
+    fn get_name(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(4);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get name")
+            .context("could not get name")?)
     }
 
-    fn get_class(&self) -> Result<u32> {
+    fn get_class(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(8);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get class")
+            .context("could not get class")?)
     }
 
-    fn get_resource_value(&self) -> Result<u32> {
+    fn get_resource_value(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(12);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get resource value")
+            .context("could not get resource value")?)
     }
 
-    fn get_data(&self) -> Result<u32> {
+    fn get_data(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.slice);
         cursor.set_position(16);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 }
 
 impl<'a> AttributeWrapper<'a> {
     /// Creates a new `AttributeWrapper`
     pub fn new(slice: &'a [u8]) -> Self {
-        AttributeWrapper { slice: slice }
+        Self { slice }
     }
 
     /// It converts the wrapper into a `AttributeBuf` which can be later manipulated
-    pub fn to_buffer(&self) -> Result<AttributeBuf> {
+    pub fn to_buffer(&self) -> Result<AttributeBuf, Error> {
         let attr = AttributeBuf::new(
             self.get_namespace()?,
             self.get_name()?,
@@ -316,16 +317,16 @@ pub struct XmlTagEndWrapper<'a> {
 
 impl<'a> XmlTagEndWrapper<'a> {
     pub fn new(raw_data: &'a [u8]) -> Self {
-        XmlTagEndWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
-    pub fn to_buffer(&self) -> Result<XmlTagEndBuf> {
+    pub fn to_buffer(&self) -> Result<XmlTagEndBuf, Error> {
         Ok(XmlTagEndBuf::new(self.get_id()?))
     }
 }
 
 impl<'a> TagEnd for XmlTagEndWrapper<'a> {
-    fn get_id(&self) -> Result<u32> {
+    fn get_id(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(5 * 4);
 
@@ -339,15 +340,15 @@ pub struct XmlTextWrapper<'a> {
 
 impl<'a> XmlTextWrapper<'a> {
     pub fn new(raw_data: &'a [u8]) -> Self {
-        XmlTextWrapper { raw_data: raw_data }
+        Self { raw_data }
     }
 
-    pub fn get_text_index(&self) -> Result<u32> {
+    pub fn get_text_index(&self) -> Result<u32, Error> {
         let mut cursor = Cursor::new(self.raw_data);
         cursor.set_position(16);
 
-        cursor
+        Ok(cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Could not get data")
+            .context("could not get data")?)
     }
 }
diff --git a/src/decoder.rs b/src/decoder.rs
index c41fc5c3a..26c536def 100644
--- a/src/decoder.rs
+++ b/src/decoder.rs
@@ -1,12 +1,13 @@
 //! Structs which contains the read data from binary documents
 
-use visitor::ModelVisitor;
-use std::io::Cursor;
+use std::io::{Cursor, Read};
+
+use failure::{Error, ResultExt};
+
 use visitor::Executor;
-use errors::*;
+use visitor::ModelVisitor;
 use visitor::*;
 use STR_ARSC;
-use std::io::Read;
 
 pub struct BufferedDecoder {
     buffer: Box<[u8]>,
@@ -27,16 +28,16 @@ impl From<Box<[u8]>> for BufferedDecoder {
 }
 
 impl BufferedDecoder {
-    pub fn from_read<R: Read>(mut read: R) -> Result<BufferedDecoder> {
+    pub fn from_read<R: Read>(mut read: R) -> Result<BufferedDecoder, Error> {
         let mut buffer = Vec::new();
         read.read_to_end(&mut buffer)
-            .chain_err(|| "could not read buffer")?;
+            .context("could not read buffer")?;
         Ok(BufferedDecoder {
             buffer: buffer.into_boxed_slice(),
         })
     }
 
-    pub fn get_decoder(&self) -> Result<Decoder> {
+    pub fn get_decoder(&self) -> Result<Decoder, Error> {
         Decoder::new(&self.buffer)
     }
 }
@@ -48,19 +49,19 @@ pub struct Decoder<'a> {
 }
 
 impl<'a> Decoder<'a> {
-    pub fn new(data: &'a [u8]) -> Result<Decoder<'a>> {
+    pub fn new(buffer_apk: &'a [u8]) -> Result<Self, Error> {
         let visitor = ModelVisitor::default();
 
-        let mut decoder = Decoder {
-            visitor: visitor,
+        let mut decoder = Self {
+            visitor,
             buffer_android: STR_ARSC,
-            buffer_apk: data,
+            buffer_apk,
         };
 
         Executor::arsc(decoder.buffer_android, &mut decoder.visitor)
-            .chain_err(|| "Could not read android lib resources")?;
+            .context("could not read Android lib resources")?;
         Executor::arsc(decoder.buffer_apk, &mut decoder.visitor)
-            .chain_err(|| "Could not read target APK resources")?;
+            .context("could not read target APK resources")?;
 
         Ok(decoder)
     }
@@ -69,7 +70,7 @@ impl<'a> Decoder<'a> {
         self.visitor.get_resources()
     }
 
-    pub fn xml_visitor<T: AsRef<[u8]>>(&self, content: &'a T) -> Result<XmlVisitor> {
+    pub fn xml_visitor<T: AsRef<[u8]>>(&self, content: &'a T) -> Result<XmlVisitor, Error> {
         let cursor = Cursor::new(content.as_ref());
         let mut visitor = XmlVisitor::new(self.get_resources());
 
diff --git a/src/encoder.rs b/src/encoder.rs
index 59e1276ba..7840290ef 100644
--- a/src/encoder.rs
+++ b/src/encoder.rs
@@ -1,17 +1,18 @@
 //! Exports the decoded binary XMLs to string XMLs
 
-use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
-use xml::common::XmlVersion;
-use model::Element as AbxmlElement;
-use std::ops::Deref;
 use std::io::Write;
-use errors::*;
-use model::Namespaces;
+use std::ops::Deref;
+
+use failure::{Error, ResultExt};
+use xml::common::XmlVersion;
+use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
+
+use model::{Element as AbxmlElement, Namespaces};
 
 pub struct Xml;
 
 impl Xml {
-    pub fn encode(namespaces: &Namespaces, element: &AbxmlElement) -> Result<String> {
+    pub fn encode(namespaces: &Namespaces, element: &AbxmlElement) -> Result<String, Error> {
         let target: Vec<u8> = Vec::new();
         let mut writer = EmitterConfig::new()
             .perform_indent(true)
@@ -24,17 +25,17 @@ impl Xml {
             standalone: Some(false),
         })?;
         Self::encode_element(&mut writer, namespaces, element)
-            .chain_err(|| "Error decoding an element")?;
+            .context("error decoding an element")?;
 
         let inner = writer.into_inner();
-        String::from_utf8(inner).chain_err(|| "Could not export XML")
+        Ok(String::from_utf8(inner).context("could not export XML")?)
     }
 
     fn encode_element<W: Write>(
         writer: &mut EventWriter<W>,
         namespaces: &Namespaces,
         element: &AbxmlElement,
-    ) -> Result<()> {
+    ) -> Result<(), Error> {
         let tag = element.get_tag();
         let tag_name = tag.get_name();
         let prefixes = tag.get_prefixes();
diff --git a/src/lib.rs b/src/lib.rs
index ce473af32..65234c88e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,7 +9,7 @@
 extern crate byteorder;
 extern crate encoding;
 #[macro_use]
-extern crate error_chain;
+extern crate failure;
 #[macro_use]
 extern crate log;
 extern crate xml;
@@ -30,16 +30,3 @@ pub mod apk;
 
 /// Contents of android's resources.arsc
 pub const STR_ARSC: &'static [u8] = include_bytes!("../resources/resources.arsc");
-
-/// Representation of library errors
-pub mod errors {
-    // Create the Error, ErrorKind, ResultExt, and Result types
-    error_chain! {
-        foreign_links {
-            Io(::std::io::Error);
-            Xml(::xml::writer::Error);
-            Utf8(::std::string::FromUtf8Error);
-            Zip(::zip::result::ZipError) #[cfg(feature = "zip_decode")];
-        }
-    }
-}
diff --git a/src/model/builder.rs b/src/model/builder.rs
index d3a1c1ecd..203dd521b 100644
--- a/src/model/builder.rs
+++ b/src/model/builder.rs
@@ -1,6 +1,7 @@
-use model::owned::OwnedBuf;
 use byteorder::{LittleEndian, WriteBytesExt};
-use errors::*;
+use failure::{Error, ResultExt};
+
+use model::owned::OwnedBuf;
 
 #[derive(Default)]
 pub struct Arsc {
@@ -12,13 +13,13 @@ impl Arsc {
         self.chunks.push(chunk);
     }
 
-    pub fn to_vec(&self) -> Result<Vec<u8>> {
+    pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
         let mut inner = Vec::new();
         let mut file_size = 0;
 
         for c in &self.chunks {
-            let encoded_chunk = c.to_vec().chain_err(|| "Could not encode a chunk")?;
+            let encoded_chunk = c.to_vec().context("could not encode a chunk")?;
             file_size += encoded_chunk.len();
 
             inner.extend(encoded_chunk);
@@ -53,13 +54,13 @@ impl Xml {
         self.chunks.push(chunk);
     }
 
-    pub fn into_vec(self) -> Result<Vec<u8>> {
+    pub fn into_vec(self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
         let mut inner = Vec::new();
         let mut file_size = 0;
 
         for c in self.chunks {
-            let encoded_chunk = c.to_vec().chain_err(|| "Could not encode a chunk")?;
+            let encoded_chunk = c.to_vec().context("could not encode a chunk")?;
             file_size += encoded_chunk.len();
 
             inner.extend(encoded_chunk);
@@ -83,16 +84,16 @@ impl Xml {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use visitor::Executor;
-    use std::io::Cursor;
     use model::owned::*;
+    use std::io::Cursor;
     use test::*;
+    use visitor::Executor;
 
     #[test]
     fn it_can_generate_a_resources_arsc_file_content() {
         let arsc = Arsc::default();
         let content = arsc.to_vec().unwrap();
-        let mut visitor = CounterChunkVisitor::new();
+        let mut visitor = CounterChunkVisitor::default();
 
         assert_eq!(vec![2, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0], content);
 
@@ -110,7 +111,7 @@ mod tests {
         arsc.push_owned(Box::new(ResourcesBuf::default()));
 
         let content = arsc.to_vec().unwrap();
-        let mut visitor = CounterChunkVisitor::new();
+        let mut visitor = CounterChunkVisitor::default();
 
         Executor::arsc(&content, &mut visitor).unwrap();
 
@@ -122,7 +123,7 @@ mod tests {
     fn it_can_generate_a_resources_xml_file_content() {
         let xml = Xml::default();
         let content = xml.into_vec().unwrap();
-        let mut visitor = CounterChunkVisitor::new();
+        let mut visitor = CounterChunkVisitor::default();
 
         assert_eq!(vec![3, 0, 8, 0, 0, 0, 0, 0], content);
 
@@ -140,7 +141,7 @@ mod tests {
         xml.push_owned(Box::new(ResourcesBuf::default()));
 
         let content = xml.into_vec().unwrap();
-        let mut visitor = CounterChunkVisitor::new();
+        let mut visitor = CounterChunkVisitor::default();
 
         let _ = Executor::xml(Cursor::new(&content), &mut visitor);
 
diff --git a/src/model/element.rs b/src/model/element.rs
index c48514a4a..1a07568e9 100644
--- a/src/model/element.rs
+++ b/src/model/element.rs
@@ -1,9 +1,7 @@
-use std::rc::Rc;
-use std::fmt::{Display, Formatter};
-use std::result::Result as StdResult;
-use std::fmt::Error as FmtError;
-use std::iter;
 use std::collections::HashMap;
+use std::fmt::{self, Display, Formatter};
+use std::iter;
+use std::rc::Rc;
 
 #[derive(Default, Debug, PartialEq, Eq, Hash)]
 pub struct Tag {
@@ -13,10 +11,7 @@ pub struct Tag {
 
 impl Tag {
     pub fn new(name: Rc<String>, prefixes: Vec<Rc<String>>) -> Self {
-        Tag {
-            name: name,
-            prefixes: prefixes,
-        }
+        Self { name, prefixes }
     }
 
     pub fn get_name(&self) -> Rc<String> {
@@ -38,9 +33,9 @@ pub struct Element {
 
 impl Element {
     pub fn new(tag: Tag, attrs: HashMap<String, String>) -> Self {
-        Element {
-            tag: tag,
-            attrs: attrs,
+        Self {
+            tag,
+            attrs,
             children: Vec::new(),
             level: 0,
         }
@@ -68,7 +63,7 @@ impl Element {
 }
 
 impl Display for Element {
-    fn fmt(&self, formatter: &mut Formatter) -> StdResult<(), FmtError> {
+    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
         let tabs = iter::repeat("\t")
             .take(self.level as usize)
             .collect::<String>();
diff --git a/src/model/mod.rs b/src/model/mod.rs
index 559177898..20a2e215c 100644
--- a/src/model/mod.rs
+++ b/src/model/mod.rs
@@ -2,17 +2,19 @@
 
 use std::collections::{BTreeMap, HashMap};
 use std::rc::Rc;
+
+use failure::Error;
+
 use model::owned::Entry;
-use errors::*;
 
+pub mod builder;
 mod element;
-mod value;
 pub mod owned;
-pub mod builder;
+mod value;
 
 pub use self::element::Element;
-pub use self::element::Tag;
 pub use self::element::ElementContainer;
+pub use self::element::Tag;
 pub use self::value::Value;
 
 use visitor::Origin;
@@ -51,13 +53,13 @@ impl Identifier for u32 {
 pub trait StringTable {
     fn get_strings_len(&self) -> u32;
     fn get_styles_len(&self) -> u32;
-    fn get_string(&self, idx: u32) -> Result<Rc<String>>;
+    fn get_string(&self, idx: u32) -> Result<Rc<String>, Error>;
 }
 
 // TODO: Decide if the trait should return Results or not
 pub trait Package {
-    fn get_id(&self) -> Result<u32>;
-    fn get_name(&self) -> Result<String>;
+    fn get_id(&self) -> Result<u32, Error>;
+    fn get_name(&self) -> Result<String, Error>;
 }
 
 pub trait Library {
@@ -68,11 +70,11 @@ pub trait Library {
         key: u32,
         namespace: Option<String>,
         prefix: &str,
-    ) -> Result<String>;
+    ) -> Result<String, Error>;
     // fn get_entries(&self) -> &Entries;
-    fn get_entry(&self, id: u32) -> Result<&Entry>;
-    fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>>;
-    fn get_spec_string(&self, str_id: u32) -> Result<Rc<String>>;
+    fn get_entry(&self, id: u32) -> Result<&Entry, Error>;
+    fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>, Error>;
+    fn get_spec_string(&self, str_id: u32) -> Result<Rc<String>, Error>;
 }
 
 pub trait LibraryBuilder<'a> {
@@ -99,38 +101,38 @@ pub trait TagStart {
     type Attribute: AttributeTrait;
 
     /// Return the ¿line in which the tag appear?
-    fn get_line(&self) -> Result<u32>;
+    fn get_line(&self) -> Result<u32, Error>;
     /// Return the content of the unknown field1
-    fn get_field1(&self) -> Result<u32>;
+    fn get_field1(&self) -> Result<u32, Error>;
     /// Return the namespace index. If there is no namespace, it will return 0xFFFFFFFF
-    fn get_namespace_index(&self) -> Result<u32>;
+    fn get_namespace_index(&self) -> Result<u32, Error>;
     /// Returns the index of the tag name on the string table
-    fn get_element_name_index(&self) -> Result<u32>;
+    fn get_element_name_index(&self) -> Result<u32, Error>;
     /// Return the content of the unknown field1
-    fn get_field2(&self) -> Result<u32>;
+    fn get_field2(&self) -> Result<u32, Error>;
     /// Return the amount of attributes this tag contains
-    fn get_attributes_amount(&self) -> Result<u32>;
+    fn get_attributes_amount(&self) -> Result<u32, Error>;
     /// Returns the ¿class?
-    fn get_class(&self) -> Result<u32>;
+    fn get_class(&self) -> Result<u32, Error>;
     /// Returns the attribute on the `index` position or error if it is greater than
     /// `get_attributes_amount`
-    fn get_attribute(&self, index: u32) -> Result<Self::Attribute>;
+    fn get_attribute(&self, index: u32) -> Result<Self::Attribute, Error>;
 }
 
 pub trait AttributeTrait {
     /// Return the namespace index. If there is no namespace, it will return 0xFFFFFFFF
-    fn get_namespace(&self) -> Result<u32>;
+    fn get_namespace(&self) -> Result<u32, Error>;
     /// Returns the index of the attribute on the string table
-    fn get_name(&self) -> Result<u32>;
+    fn get_name(&self) -> Result<u32, Error>;
     /// Returns the ¿class?
-    fn get_class(&self) -> Result<u32>;
+    fn get_class(&self) -> Result<u32, Error>;
     /// Returns the data type (see `Values`)
-    fn get_resource_value(&self) -> Result<u32>;
+    fn get_resource_value(&self) -> Result<u32, Error>;
     /// Returns the value (see `Values`)
-    fn get_data(&self) -> Result<u32>;
+    fn get_data(&self) -> Result<u32, Error>;
 
     /// Creates a `Value` depending on the data type and data value
-    fn get_value(&self) -> Result<Value> {
+    fn get_value(&self) -> Result<Value, Error> {
         let data_type = ((self.get_resource_value()? >> 24) & 0xFF) as u8;
         let data_value = self.get_data()?;
         let class = self.get_class()?;
@@ -146,60 +148,60 @@ pub trait AttributeTrait {
 }
 
 pub trait TagEnd {
-    fn get_id(&self) -> Result<u32>;
+    fn get_id(&self) -> Result<u32, Error>;
 }
 
 pub trait NamespaceStart {
-    fn get_line(&self) -> Result<u32>;
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>>;
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>>;
+    fn get_line(&self) -> Result<u32, Error>;
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error>;
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error>;
 }
 
 pub trait NamespaceEnd {
-    fn get_line(&self) -> Result<u32>;
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>>;
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>>;
+    fn get_line(&self) -> Result<u32, Error>;
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error>;
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error>;
 }
 
 pub trait TypeSpec {
-    fn get_id(&self) -> Result<u16>;
-    fn get_amount(&self) -> Result<u32>;
-    fn get_flag(&self, index: u32) -> Result<u32>;
+    fn get_id(&self) -> Result<u16, Error>;
+    fn get_amount(&self) -> Result<u32, Error>;
+    fn get_flag(&self, index: u32) -> Result<u32, Error>;
 }
 
 pub trait TableType {
     type Configuration: Configuration;
 
-    fn get_id(&self) -> Result<u8>;
-    fn get_amount(&self) -> Result<u32>;
-    fn get_configuration(&self) -> Result<Self::Configuration>;
-    fn get_entry(&self, index: u32) -> Result<Entry>;
+    fn get_id(&self) -> Result<u8, Error>;
+    fn get_amount(&self) -> Result<u32, Error>;
+    fn get_configuration(&self) -> Result<Self::Configuration, Error>;
+    fn get_entry(&self, index: u32) -> Result<Entry, Error>;
 }
 
 pub trait Configuration {
-    fn get_size(&self) -> Result<u32>;
-    fn get_mcc(&self) -> Result<u16>;
-    fn get_mnc(&self) -> Result<u16>;
-    fn get_language(&self) -> Result<String>;
-    fn get_region(&self) -> Result<String>;
-    fn get_orientation(&self) -> Result<u8>;
-    fn get_touchscreen(&self) -> Result<u8>;
-    fn get_density(&self) -> Result<u16>;
-    fn get_keyboard(&self) -> Result<u8>;
-    fn get_navigation(&self) -> Result<u8>;
-    fn get_input_flags(&self) -> Result<u8>;
-    fn get_width(&self) -> Result<u16>;
-    fn get_height(&self) -> Result<u16>;
-    fn get_sdk_version(&self) -> Result<u16>;
-    fn get_min_sdk_version(&self) -> Result<u16>;
-    fn get_screen_layout(&self) -> Result<u8>;
-    fn get_ui_mode(&self) -> Result<u8>;
-    fn get_smallest_screen(&self) -> Result<u16>;
-    fn get_screen_width(&self) -> Result<u16>;
-    fn get_screen_height(&self) -> Result<u16>;
-    fn get_locale_script(&self) -> Result<Option<String>>;
-    fn get_locale_variant(&self) -> Result<Option<String>>;
-    fn get_secondary_layout(&self) -> Result<Option<u8>>;
+    fn get_size(&self) -> Result<u32, Error>;
+    fn get_mcc(&self) -> Result<u16, Error>;
+    fn get_mnc(&self) -> Result<u16, Error>;
+    fn get_language(&self) -> Result<String, Error>;
+    fn get_region(&self) -> Result<String, Error>;
+    fn get_orientation(&self) -> Result<u8, Error>;
+    fn get_touchscreen(&self) -> Result<u8, Error>;
+    fn get_density(&self) -> Result<u16, Error>;
+    fn get_keyboard(&self) -> Result<u8, Error>;
+    fn get_navigation(&self) -> Result<u8, Error>;
+    fn get_input_flags(&self) -> Result<u8, Error>;
+    fn get_width(&self) -> Result<u16, Error>;
+    fn get_height(&self) -> Result<u16, Error>;
+    fn get_sdk_version(&self) -> Result<u16, Error>;
+    fn get_min_sdk_version(&self) -> Result<u16, Error>;
+    fn get_screen_layout(&self) -> Result<u8, Error>;
+    fn get_ui_mode(&self) -> Result<u8, Error>;
+    fn get_smallest_screen(&self) -> Result<u16, Error>;
+    fn get_screen_width(&self) -> Result<u16, Error>;
+    fn get_screen_height(&self) -> Result<u16, Error>;
+    fn get_locale_script(&self) -> Result<Option<String>, Error>;
+    fn get_locale_variant(&self) -> Result<Option<String>, Error>;
+    fn get_secondary_layout(&self) -> Result<Option<u8>, Error>;
 }
 
 #[cfg(test)]
diff --git a/src/model/owned/mod.rs b/src/model/owned/mod.rs
index 85c7c0392..238f5c6c7 100644
--- a/src/model/owned/mod.rs
+++ b/src/model/owned/mod.rs
@@ -1,47 +1,41 @@
-use errors::*;
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::{Error, ResultExt};
 
-pub use self::resources::ResourcesBuf;
-pub use self::string_table::StringTableBuf;
-pub use self::string_table::Encoding;
-pub use self::xml::XmlTagStartBuf;
-pub use self::xml::XmlTagEndBuf;
-pub use self::xml::XmlNamespaceStartBuf;
-pub use self::xml::XmlNamespaceEndBuf;
-pub use self::xml::AttributeBuf;
 pub use self::package::PackageBuf;
+pub use self::resources::ResourcesBuf;
+pub use self::string_table::{Encoding, StringTableBuf};
+pub use self::table_type::{ComplexEntry, ConfigurationBuf, Entry, EntryHeader, SimpleEntry,
+                           TableTypeBuf};
 pub use self::table_type_spec::TableTypeSpecBuf;
-pub use self::table_type::ConfigurationBuf;
-pub use self::table_type::TableTypeBuf;
-pub use self::table_type::{ComplexEntry, Entry, EntryHeader, SimpleEntry};
+pub use self::xml::{AttributeBuf, XmlNamespaceEndBuf, XmlNamespaceStartBuf, XmlTagEndBuf,
+                    XmlTagStartBuf};
 
+mod package;
 mod resources;
 mod string_table;
-mod xml;
-mod package;
-mod table_type_spec;
 mod table_type;
+mod table_type_spec;
+mod xml;
 
 /// Implementors are able to be converted to well formed chunks as expected on `ChunkLoaderStream`
 pub trait OwnedBuf {
     /// Token that identifies the current chunk
     fn get_token(&self) -> u16;
     /// Return the bytes corresponding to chunk's body
-    fn get_body_data(&self) -> Result<Vec<u8>>;
+    fn get_body_data(&self) -> Result<Vec<u8>, Error>;
 
     /// Return the bytes corresponding to chunk's header
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         Ok(Vec::new())
     }
 
     /// Convert the given `OwnedBuf` to a well formed chunk in form of vector of bytes
-    fn to_vec(&self) -> Result<Vec<u8>> {
+    fn to_vec(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
-        let body = self.get_body_data()
-            .chain_err(|| "Could not read chunk body")?;
+        let body = self.get_body_data().context("could not read chunk body")?;
 
         self.write_header(&mut out, &body)
-            .chain_err(|| "Could not write header")?;
+            .context("could not write header")?;
 
         out.extend(body.iter());
 
@@ -50,7 +44,7 @@ pub trait OwnedBuf {
 
     /// Writes the header to the output buffer. It writes token, header size and chunk_size and
     /// then the data returned by `get_header`.
-    fn write_header(&self, buffer: &mut Vec<u8>, body: &[u8]) -> Result<()> {
+    fn write_header(&self, buffer: &mut Vec<u8>, body: &[u8]) -> Result<(), Error> {
         let header = self.get_header()?;
         let header_size = header.len() as u16 + 8;
 
diff --git a/src/model/owned/package.rs b/src/model/owned/package.rs
index 7d74dfc4b..935fc173c 100644
--- a/src/model/owned/package.rs
+++ b/src/model/owned/package.rs
@@ -1,9 +1,10 @@
-use model::owned::OwnedBuf;
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use chunks::*;
-use errors::*;
 use encoding::codec::utf_16;
 use encoding::Encoding;
+use model::owned::OwnedBuf;
 
 #[derive(Default)]
 pub struct PackageBuf {
@@ -14,18 +15,17 @@ pub struct PackageBuf {
 
 #[allow(dead_code)]
 impl PackageBuf {
-    pub fn new(id: u32, package_name: String) -> Result<Self> {
-        if package_name.as_bytes().len() > 256 {
-            return Err("Can not create a package with a length greater than 256".into());
-        }
-
-        let package = PackageBuf {
-            id: id,
-            package_name: package_name,
+    pub fn new(id: u32, package_name: String) -> Result<Self, Error> {
+        ensure!(
+            package_name.as_bytes().len() <= 256,
+            "can not create a package with a length greater than 256"
+        );
+
+        Ok(Self {
+            id,
+            package_name,
             inner_chunks: Vec::new(),
-        };
-
-        Ok(package)
+        })
     }
 
     pub fn add_chunk(&mut self, chunk: Box<OwnedBuf>) {
@@ -38,7 +38,7 @@ impl OwnedBuf for PackageBuf {
         TOKEN_PACKAGE
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         for c in &self.inner_chunks {
@@ -49,15 +49,13 @@ impl OwnedBuf for PackageBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut buffer = Vec::new();
         let mut encoder = utf_16::UTF_16LE_ENCODING.raw_encoder();
         let mut encoded_string = Vec::new();
         let (size, error) = encoder.raw_feed(&self.package_name, &mut encoded_string);
 
-        if error.is_some() {
-            return Err("Error encoding package name as UTF-16".into());
-        }
+        ensure!(error.is_none(), "error encoding package name as UTF-16");
 
         buffer.write_u32::<LittleEndian>(self.id)?;
         buffer.extend(encoded_string);
@@ -80,9 +78,9 @@ mod tests {
     use super::*;
     use chunks::{Chunk, ChunkLoaderStream, PackageWrapper};
     use model::owned::StringTableBuf;
+    use model::StringTable;
     use std::io::Cursor;
     use std::iter;
-    use model::StringTable;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
@@ -148,9 +146,7 @@ mod tests {
 
     #[test]
     fn it_can_create_a_package_with_the_maximum_length() {
-        let target = iter::repeat('\u{1F624}')
-            .take((256 / 4))
-            .collect::<String>();
+        let target = iter::repeat('\u{1F624}').take(256 / 4).collect::<String>();
         let package = PackageBuf::new(1, target);
 
         assert!(package.is_ok());
diff --git a/src/model/owned/resources.rs b/src/model/owned/resources.rs
index 241bb8cf1..5c5a3b822 100644
--- a/src/model/owned/resources.rs
+++ b/src/model/owned/resources.rs
@@ -1,7 +1,8 @@
-use model::owned::OwnedBuf;
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use chunks::*;
-use errors::*;
+use model::owned::OwnedBuf;
 
 #[derive(Default)]
 pub struct ResourcesBuf {
@@ -23,7 +24,7 @@ impl OwnedBuf for ResourcesBuf {
         TOKEN_RESOURCE
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         for r in &self.resources {
@@ -37,8 +38,8 @@ impl OwnedBuf for ResourcesBuf {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use test::compare_chunks;
     use raw_chunks;
+    use test::compare_chunks;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/owned/string_table.rs b/src/model/owned/string_table.rs
index a1a687042..151c5b6e4 100644
--- a/src/model/owned/string_table.rs
+++ b/src/model/owned/string_table.rs
@@ -1,11 +1,13 @@
-use model::owned::OwnedBuf;
-use byteorder::{LittleEndian, WriteBytesExt};
-use errors::*;
-use chunks::*;
-use model::StringTable;
 use std::rc::Rc;
+
+use byteorder::{LittleEndian, WriteBytesExt};
 use encoding::codec::{utf_16, utf_8};
 use encoding::Encoding as EncodingTrait;
+use failure::Error;
+
+use chunks::*;
+use model::owned::OwnedBuf;
+use model::StringTable;
 
 #[derive(Clone, Copy, PartialEq)]
 pub enum Encoding {
@@ -20,8 +22,8 @@ pub struct StringTableBuf {
 }
 
 impl Default for StringTableBuf {
-    fn default() -> StringTableBuf {
-        StringTableBuf {
+    fn default() -> Self {
+        Self {
             strings: Vec::new(),
             styles: Vec::new(),
             encoding: Encoding::Utf8,
@@ -48,7 +50,7 @@ impl OwnedBuf for StringTableBuf {
         TOKEN_STRING_TABLE
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         let flags = if self.encoding == Encoding::Utf8 {
@@ -73,7 +75,7 @@ impl OwnedBuf for StringTableBuf {
         Ok(out)
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         let mut string_offsets: Vec<u32> = Vec::new();
@@ -94,9 +96,7 @@ impl OwnedBuf for StringTableBuf {
             let mut encoded_string = Vec::new();
             let (size, error) = encoder.raw_feed(string, &mut encoded_string);
 
-            if error.is_some() {
-                return Err("Error encoding string".into());
-            }
+            ensure!(error.is_none(), "error encoding string");
 
             // Write size
             let low = (size & 0xFF) as u8;
@@ -141,10 +141,11 @@ impl StringTable for StringTableBuf {
         self.styles.len() as u32
     }
 
-    fn get_string(&self, idx: u32) -> Result<Rc<String>> {
-        match self.strings.get(idx as usize) {
-            None => Err("String not found".into()),
-            Some(s) => Ok(s.clone()),
+    fn get_string(&self, idx: u32) -> Result<Rc<String>, Error> {
+        if let Some(s) = self.strings.get(idx as usize) {
+            Ok(s.clone())
+        } else {
+            bail!("string not found")
         }
     }
 }
@@ -152,8 +153,8 @@ impl StringTable for StringTableBuf {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use test::compare_chunks;
     use raw_chunks;
+    use test::compare_chunks;
 
     #[test]
     fn it_can_generate_an_empty_chunk() {
diff --git a/src/model/owned/table_type/configuration.rs b/src/model/owned/table_type/configuration.rs
index 0b23683e5..ea7a390ad 100644
--- a/src/model/owned/table_type/configuration.rs
+++ b/src/model/owned/table_type/configuration.rs
@@ -1,9 +1,11 @@
-use model::Configuration;
-use chunks::table_type::Region;
-use errors::*;
-use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 use std::io::Cursor;
 
+use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
+use failure::Error;
+
+use chunks::table_type::Region;
+use model::Configuration;
+
 #[derive(Clone, Default)]
 pub struct ConfigurationBuf {
     size: u32,
@@ -33,7 +35,7 @@ pub struct ConfigurationBuf {
 }
 
 impl ConfigurationBuf {
-    pub fn to_vec(&self) -> Result<Vec<u8>> {
+    pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
         let mut buffer = Vec::new();
 
         buffer.write_u32::<LittleEndian>(self.size)?;
@@ -75,7 +77,7 @@ impl ConfigurationBuf {
         Ok(buffer)
     }
 
-    pub fn from_cursor(buffer: Vec<u8>) -> Result<Self> {
+    pub fn from_cursor(buffer: Vec<u8>) -> Result<Self, Error> {
         let original_size = buffer.len() as u32;
         let mut cursor = Cursor::new(buffer);
         let size = cursor.read_u32::<LittleEndian>()?;
@@ -138,121 +140,119 @@ impl ConfigurationBuf {
             // TODO: Read bytes
         }
 
-        let rc = ConfigurationBuf {
-            size: size,
-            original_size: original_size,
-            mcc: mcc,
-            mnc: mnc,
+        Ok(Self {
+            size,
+            original_size,
+            mcc,
+            mnc,
             language: str_lang,
             region: str_reg,
-            orientation: orientation,
-            touchscreen: touchscreen,
-            density: density,
-            keyboard: keyboard,
-            navigation: navigation,
-            input_flags: input_flags,
-            width: width,
-            height: height,
-            sdk_version: sdk_version,
-            min_sdk_version: min_sdk_version,
-            screen_layout: screen_layout,
-            ui_mode: ui_mode,
-            smallest_screen: smallest_screen,
-            screen_width_dp: screen_width_dp,
-            screen_height_dp: screen_height_dp,
+            orientation,
+            touchscreen,
+            density,
+            keyboard,
+            navigation,
+            input_flags,
+            width,
+            height,
+            sdk_version,
+            min_sdk_version,
+            screen_layout,
+            ui_mode,
+            smallest_screen,
+            screen_width_dp,
+            screen_height_dp,
             locale_script: None,
             locale_variant: None,
             secondary_screen_layout: None,
-        };
-
-        Ok(rc)
+        })
     }
 }
 
 impl Configuration for ConfigurationBuf {
-    fn get_size(&self) -> Result<u32> {
+    fn get_size(&self) -> Result<u32, Error> {
         Ok(self.size)
     }
 
-    fn get_mcc(&self) -> Result<u16> {
+    fn get_mcc(&self) -> Result<u16, Error> {
         Ok(self.mcc)
     }
 
-    fn get_mnc(&self) -> Result<u16> {
+    fn get_mnc(&self) -> Result<u16, Error> {
         Ok(self.mnc)
     }
 
-    fn get_language(&self) -> Result<String> {
+    fn get_language(&self) -> Result<String, Error> {
         let region = Region::from(self.language.as_ref());
         Ok(region.to_string())
     }
 
-    fn get_region(&self) -> Result<String> {
+    fn get_region(&self) -> Result<String, Error> {
         let region = Region::from(self.region.as_ref());
         Ok(region.to_string())
     }
 
-    fn get_orientation(&self) -> Result<u8> {
+    fn get_orientation(&self) -> Result<u8, Error> {
         Ok(self.orientation)
     }
 
-    fn get_touchscreen(&self) -> Result<u8> {
+    fn get_touchscreen(&self) -> Result<u8, Error> {
         Ok(self.touchscreen)
     }
 
-    fn get_density(&self) -> Result<u16> {
+    fn get_density(&self) -> Result<u16, Error> {
         Ok(self.density)
     }
 
-    fn get_keyboard(&self) -> Result<u8> {
+    fn get_keyboard(&self) -> Result<u8, Error> {
         Ok(self.keyboard)
     }
 
-    fn get_navigation(&self) -> Result<u8> {
+    fn get_navigation(&self) -> Result<u8, Error> {
         Ok(self.navigation)
     }
 
-    fn get_input_flags(&self) -> Result<u8> {
+    fn get_input_flags(&self) -> Result<u8, Error> {
         Ok(self.input_flags)
     }
 
-    fn get_width(&self) -> Result<u16> {
+    fn get_width(&self) -> Result<u16, Error> {
         Ok(self.width)
     }
 
-    fn get_height(&self) -> Result<u16> {
+    fn get_height(&self) -> Result<u16, Error> {
         Ok(self.height)
     }
 
-    fn get_sdk_version(&self) -> Result<u16> {
+    fn get_sdk_version(&self) -> Result<u16, Error> {
         Ok(self.sdk_version)
     }
 
-    fn get_min_sdk_version(&self) -> Result<u16> {
+    fn get_min_sdk_version(&self) -> Result<u16, Error> {
         Ok(self.min_sdk_version)
     }
 
-    fn get_screen_layout(&self) -> Result<u8> {
+    fn get_screen_layout(&self) -> Result<u8, Error> {
         Ok(self.screen_layout)
     }
 
-    fn get_ui_mode(&self) -> Result<u8> {
+    fn get_ui_mode(&self) -> Result<u8, Error> {
         Ok(self.ui_mode)
     }
 
-    fn get_smallest_screen(&self) -> Result<u16> {
+    fn get_smallest_screen(&self) -> Result<u16, Error> {
         Ok(self.smallest_screen)
     }
 
-    fn get_screen_width(&self) -> Result<u16> {
+    fn get_screen_width(&self) -> Result<u16, Error> {
         Ok(self.screen_width_dp)
     }
 
-    fn get_screen_height(&self) -> Result<u16> {
+    fn get_screen_height(&self) -> Result<u16, Error> {
         Ok(self.screen_height_dp)
     }
 
-    fn get_locale_script(&self) -> Result<Option<String>> {
+    fn get_locale_script(&self) -> Result<Option<String>, Error> {
         let out = match self.locale_script {
             Some(ref s) => Some(s.clone()),
             None => None,
@@ -261,7 +261,7 @@ impl Configuration for ConfigurationBuf {
         Ok(out)
     }
 
-    fn get_locale_variant(&self) -> Result<Option<String>> {
+    fn get_locale_variant(&self) -> Result<Option<String>, Error> {
         let out = match self.locale_variant {
             Some(ref s) => Some(s.clone()),
             None => None,
@@ -270,7 +270,7 @@ impl Configuration for ConfigurationBuf {
         Ok(out)
     }
 
-    fn get_secondary_layout(&self) -> Result<Option<u8>> {
+    fn get_secondary_layout(&self) -> Result<Option<u8>, Error> {
         Ok(self.secondary_screen_layout)
     }
 }
diff --git a/src/model/owned/table_type/entry.rs b/src/model/owned/table_type/entry.rs
index 2b4423083..6a70d25b3 100644
--- a/src/model/owned/table_type/entry.rs
+++ b/src/model/owned/table_type/entry.rs
@@ -1,5 +1,5 @@
-use errors::*;
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
 
 const MASK_COMPLEX: u16 = 0x0001;
 
@@ -12,10 +12,10 @@ pub struct EntryHeader {
 
 impl EntryHeader {
     pub fn new(header_size: u16, flags: u16, key_index: u32) -> Self {
-        EntryHeader {
-            header_size: header_size,
-            flags: flags,
-            key_index: key_index,
+        Self {
+            header_size,
+            flags,
+            key_index,
         }
     }
 
@@ -38,11 +38,11 @@ pub struct SimpleEntry {
 
 impl SimpleEntry {
     pub fn new(id: u32, key_index: u32, value_type: u8, value_data: u32) -> Self {
-        SimpleEntry {
-            id: id,
-            key_index: key_index,
-            value_type: value_type,
-            value_data: value_data,
+        Self {
+            id,
+            key_index,
+            value_type,
+            value_data,
         }
     }
 
@@ -62,7 +62,7 @@ impl SimpleEntry {
         self.value_data
     }
 
-    pub fn to_vec(&self) -> Result<Vec<u8>> {
+    pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         // Header size
@@ -96,11 +96,11 @@ pub struct ComplexEntry {
 
 impl ComplexEntry {
     pub fn new(id: u32, key_index: u32, parent_entry_id: u32, entries: Vec<SimpleEntry>) -> Self {
-        ComplexEntry {
-            id: id,
-            key_index: key_index,
-            parent_entry_id: parent_entry_id,
-            entries: entries,
+        Self {
+            id,
+            key_index,
+            parent_entry_id,
+            entries,
         }
     }
 
@@ -126,7 +126,7 @@ impl ComplexEntry {
         &self.entries
     }
 
-    pub fn to_vec(&self) -> Result<Vec<u8>> {
+    pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         // Header size
@@ -175,17 +175,17 @@ pub enum Entry {
 }
 
 impl Entry {
-    pub fn simple(&self) -> Result<&SimpleEntry> {
+    pub fn simple(&self) -> Result<&SimpleEntry, Error> {
         match *self {
             Entry::Simple(ref simple) => Ok(simple),
-            _ => Err("Asked for a complex entry on a simple one".into()),
+            _ => Err(format_err!("asked for a complex entry on a simple one")),
         }
     }
 
-    pub fn complex(&self) -> Result<&ComplexEntry> {
+    pub fn complex(&self) -> Result<&ComplexEntry, Error> {
         match *self {
             Entry::Complex(ref complex) => Ok(complex),
-            _ => Err("Asked for a simple entry on a complex one".into()),
+            _ => Err(format_err!("asked for a simple entry on a complex one")),
         }
     }
 
@@ -212,7 +212,7 @@ impl Entry {
         }
     }
 
-    pub fn to_vec(&self) -> Result<Vec<u8>> {
+    pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
         match *self {
             Entry::Complex(ref complex) => complex.to_vec(),
             Entry::Simple(ref simple) => simple.to_vec(),
diff --git a/src/model/owned/table_type/mod.rs b/src/model/owned/table_type/mod.rs
index 46a8bbdf3..4c2425e85 100644
--- a/src/model/owned/table_type/mod.rs
+++ b/src/model/owned/table_type/mod.rs
@@ -1,7 +1,8 @@
+use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use model::owned::OwnedBuf;
-use errors::*;
 use model::TableType;
-use byteorder::{LittleEndian, WriteBytesExt};
 
 mod configuration;
 mod entry;
@@ -17,9 +18,9 @@ pub struct TableTypeBuf {
 
 impl TableTypeBuf {
     pub fn new(id: u8, config: ConfigurationBuf) -> Self {
-        TableTypeBuf {
-            id: id,
-            config: config,
+        Self {
+            id,
+            config,
             entries: Vec::new(),
         }
     }
@@ -34,7 +35,7 @@ impl OwnedBuf for TableTypeBuf {
         0x201
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         let mut i = 0;
@@ -58,7 +59,7 @@ impl OwnedBuf for TableTypeBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         let vec_config = self.config.to_vec()?;
@@ -75,23 +76,23 @@ impl OwnedBuf for TableTypeBuf {
 impl TableType for TableTypeBuf {
     type Configuration = ConfigurationBuf;
 
-    fn get_id(&self) -> Result<u8> {
+    fn get_id(&self) -> Result<u8, Error> {
         Ok(self.id)
     }
 
-    fn get_amount(&self) -> Result<u32> {
+    fn get_amount(&self) -> Result<u32, Error> {
         Ok(self.entries.len() as u32)
     }
 
-    fn get_configuration(&self) -> Result<Self::Configuration> {
+    fn get_configuration(&self) -> Result<Self::Configuration, Error> {
         Ok(self.config.clone())
     }
 
-    fn get_entry(&self, index: u32) -> Result<Entry> {
+    fn get_entry(&self, index: u32) -> Result<Entry, Error> {
         self.entries
             .get(index as usize)
             .cloned()
-            .ok_or_else(|| "Entry out of bound".into())
+            .ok_or_else(|| format_err!("entry out of bound"))
     }
 }
 
@@ -99,10 +100,10 @@ impl TableType for TableTypeBuf {
 mod tests {
     use super::*;
     use chunks::*;
+    use model::owned::OwnedBuf;
     use model::TableType;
     use raw_chunks;
     use test::compare_chunks;
-    use model::owned::OwnedBuf;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/owned/table_type_spec.rs b/src/model/owned/table_type_spec.rs
index 66159538a..77eb4b9f8 100644
--- a/src/model/owned/table_type_spec.rs
+++ b/src/model/owned/table_type_spec.rs
@@ -1,7 +1,8 @@
+use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use model::owned::OwnedBuf;
-use errors::*;
 use model::TypeSpec;
-use byteorder::{LittleEndian, WriteBytesExt};
 
 pub struct TableTypeSpecBuf {
     id: u16,
@@ -10,8 +11,8 @@ pub struct TableTypeSpecBuf {
 
 impl TableTypeSpecBuf {
     pub fn new(id: u16) -> Self {
-        TableTypeSpecBuf {
-            id: id,
+        Self {
+            id,
             flags: Vec::new(),
         }
     }
@@ -26,7 +27,7 @@ impl OwnedBuf for TableTypeSpecBuf {
         0x202
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         for flag in &self.flags {
@@ -36,7 +37,7 @@ impl OwnedBuf for TableTypeSpecBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.id as u32)?;
@@ -47,28 +48,28 @@ impl OwnedBuf for TableTypeSpecBuf {
 }
 
 impl TypeSpec for TableTypeSpecBuf {
-    fn get_id(&self) -> Result<u16> {
+    fn get_id(&self) -> Result<u16, Error> {
         Ok(self.id)
     }
-    fn get_amount(&self) -> Result<u32> {
+    fn get_amount(&self) -> Result<u32, Error> {
         Ok(self.flags.len() as u32)
     }
 
-    fn get_flag(&self, index: u32) -> Result<u32> {
+    fn get_flag(&self, index: u32) -> Result<u32, Error> {
         self.flags
             .get(index as usize)
             .cloned()
-            .ok_or_else(|| "Flag out of bounds".into())
+            .ok_or_else(|| format_err!("flag out of bounds"))
     }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
+    use chunks::*;
     use model::owned::OwnedBuf;
-    use test::compare_chunks;
     use raw_chunks;
-    use chunks::*;
+    use test::compare_chunks;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/owned/xml/attribute.rs b/src/model/owned/xml/attribute.rs
index fde12d4b9..54b5c34bd 100644
--- a/src/model/owned/xml/attribute.rs
+++ b/src/model/owned/xml/attribute.rs
@@ -1,4 +1,5 @@
-use errors::*;
+use failure::Error;
+
 use model::AttributeTrait;
 
 #[derive(Clone)]
@@ -12,34 +13,34 @@ pub struct AttributeBuf {
 
 impl AttributeBuf {
     pub fn new(namespace: u32, name: u32, class: u32, value: u32, data: u32) -> Self {
-        AttributeBuf {
-            namespace: namespace,
-            name: name,
-            class: class,
-            value: value,
-            data: data,
+        Self {
+            namespace,
+            name,
+            class,
+            value,
+            data,
         }
     }
 }
 
 impl AttributeTrait for AttributeBuf {
-    fn get_namespace(&self) -> Result<u32> {
+    fn get_namespace(&self) -> Result<u32, Error> {
         Ok(self.namespace)
     }
 
-    fn get_name(&self) -> Result<u32> {
+    fn get_name(&self) -> Result<u32, Error> {
         Ok(self.name)
     }
 
-    fn get_class(&self) -> Result<u32> {
+    fn get_class(&self) -> Result<u32, Error> {
         Ok(self.class)
     }
 
-    fn get_resource_value(&self) -> Result<u32> {
+    fn get_resource_value(&self) -> Result<u32, Error> {
         Ok(self.value)
     }
 
-    fn get_data(&self) -> Result<u32> {
+    fn get_data(&self) -> Result<u32, Error> {
         Ok(self.data)
     }
 }
diff --git a/src/model/owned/xml/namespace_end.rs b/src/model/owned/xml/namespace_end.rs
index 3631daf83..1e88cf360 100644
--- a/src/model/owned/xml/namespace_end.rs
+++ b/src/model/owned/xml/namespace_end.rs
@@ -1,10 +1,11 @@
-use model::owned::OwnedBuf;
+use std::rc::Rc;
+
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use chunks::*;
-use errors::*;
-use std::rc::Rc;
-use model::NamespaceEnd;
-use model::StringTable;
+use model::owned::OwnedBuf;
+use model::{NamespaceEnd, StringTable};
 
 pub struct XmlNamespaceEndBuf {
     line: u32,
@@ -14,26 +15,26 @@ pub struct XmlNamespaceEndBuf {
 
 impl XmlNamespaceEndBuf {
     pub fn new(line: u32, prefix_index: u32, namespace_index: u32) -> Self {
-        XmlNamespaceEndBuf {
-            line: line,
-            prefix_index: prefix_index,
-            namespace_index: namespace_index,
+        Self {
+            line,
+            prefix_index,
+            namespace_index,
         }
     }
 }
 
 impl NamespaceEnd for XmlNamespaceEndBuf {
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         Ok(self.line)
     }
 
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let string = string_table.get_string(self.prefix_index)?;
 
         Ok(string)
     }
 
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let string = string_table.get_string(self.namespace_index)?;
 
         Ok(string)
@@ -45,7 +46,7 @@ impl OwnedBuf for XmlNamespaceEndBuf {
         TOKEN_XML_END_NAMESPACE
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.prefix_index)?;
@@ -54,7 +55,7 @@ impl OwnedBuf for XmlNamespaceEndBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.line)?;
@@ -68,8 +69,8 @@ impl OwnedBuf for XmlNamespaceEndBuf {
 mod tests {
     use super::*;
     use chunks::XmlNamespaceEndWrapper;
-    use test::compare_chunks;
     use raw_chunks::EXAMPLE_NAMESPACE_END;
+    use test::compare_chunks;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/owned/xml/namespace_start.rs b/src/model/owned/xml/namespace_start.rs
index 3a781be1b..584633731 100644
--- a/src/model/owned/xml/namespace_start.rs
+++ b/src/model/owned/xml/namespace_start.rs
@@ -1,10 +1,11 @@
-use model::owned::OwnedBuf;
+use std::rc::Rc;
+
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use chunks::*;
-use errors::*;
-use std::rc::Rc;
-use model::NamespaceStart;
-use model::StringTable;
+use model::owned::OwnedBuf;
+use model::{NamespaceStart, StringTable};
 
 pub struct XmlNamespaceStartBuf {
     line: u32,
@@ -14,26 +15,26 @@ pub struct XmlNamespaceStartBuf {
 
 impl XmlNamespaceStartBuf {
     pub fn new(line: u32, prefix_index: u32, namespace_index: u32) -> Self {
-        XmlNamespaceStartBuf {
-            line: line,
-            prefix_index: prefix_index,
-            namespace_index: namespace_index,
+        Self {
+            line,
+            prefix_index,
+            namespace_index,
         }
     }
 }
 
 impl NamespaceStart for XmlNamespaceStartBuf {
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         Ok(self.line)
     }
 
-    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_prefix<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let string = string_table.get_string(self.prefix_index)?;
 
         Ok(string)
     }
 
-    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>> {
+    fn get_namespace<S: StringTable>(&self, string_table: &S) -> Result<Rc<String>, Error> {
         let string = string_table.get_string(self.namespace_index)?;
 
         Ok(string)
@@ -45,7 +46,7 @@ impl OwnedBuf for XmlNamespaceStartBuf {
         TOKEN_XML_START_NAMESPACE
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.prefix_index)?;
@@ -54,7 +55,7 @@ impl OwnedBuf for XmlNamespaceStartBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.line)?;
@@ -68,8 +69,8 @@ impl OwnedBuf for XmlNamespaceStartBuf {
 mod tests {
     use super::*;
     use chunks::XmlNamespaceStartWrapper;
-    use test::{compare_chunks, FakeStringTable};
     use raw_chunks::EXAMPLE_NAMESPACE_START;
+    use test::{compare_chunks, FakeStringTable};
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/owned/xml/tag_end.rs b/src/model/owned/xml/tag_end.rs
index be2312142..cb0a0fc27 100644
--- a/src/model/owned/xml/tag_end.rs
+++ b/src/model/owned/xml/tag_end.rs
@@ -1,7 +1,8 @@
-use model::owned::OwnedBuf;
-use chunks::TOKEN_XML_TAG_END;
 use byteorder::{LittleEndian, WriteBytesExt};
-use errors::*;
+use failure::Error;
+
+use chunks::TOKEN_XML_TAG_END;
+use model::owned::OwnedBuf;
 use model::TagEnd;
 
 pub struct XmlTagEndBuf {
@@ -10,7 +11,7 @@ pub struct XmlTagEndBuf {
 
 impl XmlTagEndBuf {
     pub fn new(id: u32) -> Self {
-        XmlTagEndBuf { id: id }
+        Self { id }
     }
 }
 
@@ -19,7 +20,7 @@ impl OwnedBuf for XmlTagEndBuf {
         TOKEN_XML_TAG_END
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         // ??
@@ -30,7 +31,7 @@ impl OwnedBuf for XmlTagEndBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         // Amount of writes
@@ -43,7 +44,7 @@ impl OwnedBuf for XmlTagEndBuf {
 }
 
 impl TagEnd for XmlTagEndBuf {
-    fn get_id(&self) -> Result<u32> {
+    fn get_id(&self) -> Result<u32, Error> {
         Ok(self.id)
     }
 }
@@ -52,8 +53,8 @@ impl TagEnd for XmlTagEndBuf {
 mod tests {
     use super::*;
     use chunks::*;
-    use test::compare_chunks;
     use raw_chunks;
+    use test::compare_chunks;
 
     #[test]
     fn it_can_generate_an_empty_chunk() {
diff --git a/src/model/owned/xml/tag_start.rs b/src/model/owned/xml/tag_start.rs
index dacfcae44..3333ab424 100644
--- a/src/model/owned/xml/tag_start.rs
+++ b/src/model/owned/xml/tag_start.rs
@@ -1,10 +1,9 @@
-use model::owned::OwnedBuf;
-use model::TagStart;
 use byteorder::{LittleEndian, WriteBytesExt};
+use failure::Error;
+
 use chunks::*;
-use errors::*;
-use model::owned::AttributeBuf;
-use model::AttributeTrait;
+use model::owned::{AttributeBuf, OwnedBuf};
+use model::{AttributeTrait, TagStart};
 
 /// Representation of a XML Tag start chunk
 pub struct XmlTagStartBuf {
@@ -26,22 +25,15 @@ pub struct XmlTagStartBuf {
 
 impl XmlTagStartBuf {
     /// Creates a new `XmlTagStartBuf` with the given data
-    pub fn new(
-        line: u32,
-        field1: u32,
-        namespace: u32,
-        name_index: u32,
-        field2: u32,
-        class: u32,
-    ) -> Self {
-        XmlTagStartBuf {
+    pub fn new(line: u32, field1: u32, namespace: u32, name: u32, field2: u32, class: u32) -> Self {
+        Self {
             attributes: Vec::new(),
-            name: name_index,
-            namespace: namespace,
-            line: line,
-            field1: field1,
-            field2: field2,
-            class: class,
+            name,
+            namespace,
+            line,
+            field1,
+            field2,
+            class,
         }
     }
 
@@ -54,42 +46,40 @@ impl XmlTagStartBuf {
 impl TagStart for XmlTagStartBuf {
     type Attribute = AttributeBuf;
 
-    fn get_line(&self) -> Result<u32> {
+    fn get_line(&self) -> Result<u32, Error> {
         Ok(self.line)
     }
 
-    fn get_field1(&self) -> Result<u32> {
+    fn get_field1(&self) -> Result<u32, Error> {
         Ok(self.field1)
     }
 
-    fn get_namespace_index(&self) -> Result<u32> {
+    fn get_namespace_index(&self) -> Result<u32, Error> {
         Ok(self.namespace)
     }
 
-    fn get_element_name_index(&self) -> Result<u32> {
+    fn get_element_name_index(&self) -> Result<u32, Error> {
         Ok(self.name)
     }
 
-    fn get_field2(&self) -> Result<u32> {
+    fn get_field2(&self) -> Result<u32, Error> {
         Ok(self.field2)
     }
 
-    fn get_attributes_amount(&self) -> Result<u32> {
+    fn get_attributes_amount(&self) -> Result<u32, Error> {
         Ok(self.attributes.len() as u32)
     }
 
-    fn get_class(&self) -> Result<u32> {
+    fn get_class(&self) -> Result<u32, Error> {
         Ok(self.class)
     }
 
-    fn get_attribute(&self, index: u32) -> Result<Self::Attribute> {
-        if index as usize >= self.attributes.len() {
-            return Err("Requested attribute out of bounds".into());
+    fn get_attribute(&self, index: u32) -> Result<Self::Attribute, Error> {
+        if let Some(attr) = self.attributes.get(index as usize) {
+            Ok(attr.clone())
+        } else {
+            bail!("requested attribute out of bounds")
         }
-
-        let attr = &self.attributes[index as usize];
-
-        Ok(attr.clone())
     }
 }
 
@@ -98,7 +88,7 @@ impl OwnedBuf for XmlTagStartBuf {
         TOKEN_XML_TAG_START
     }
 
-    fn get_body_data(&self) -> Result<Vec<u8>> {
+    fn get_body_data(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.namespace)?;
@@ -118,7 +108,7 @@ impl OwnedBuf for XmlTagStartBuf {
         Ok(out)
     }
 
-    fn get_header(&self) -> Result<Vec<u8>> {
+    fn get_header(&self) -> Result<Vec<u8>, Error> {
         let mut out = Vec::new();
 
         out.write_u32::<LittleEndian>(self.line)?;
@@ -131,10 +121,10 @@ impl OwnedBuf for XmlTagStartBuf {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use chunks::XmlTagStartWrapper;
     use model::owned::AttributeBuf;
     use raw_chunks::EXAMPLE_TAG_START;
     use test::compare_chunks;
-    use chunks::XmlTagStartWrapper;
 
     #[test]
     fn it_can_generate_a_chunk_with_the_given_data() {
diff --git a/src/model/value.rs b/src/model/value.rs
index 26aa33bbb..f3f9148a9 100644
--- a/src/model/value.rs
+++ b/src/model/value.rs
@@ -1,6 +1,7 @@
 use std::mem;
 use std::string::ToString;
-use errors::*;
+
+use failure::Error;
 
 const TOKEN_TYPE_REFERENCE_ID: u8 = 0x01;
 const TOKEN_TYPE_ATTRIBUTE_REFERENCE_ID: u8 = 0x02;
@@ -78,7 +79,7 @@ impl ToString for Value {
 impl Value {
     /// Creates a new `Value`. If the payload can not be interpreted by the given `value_type`, it
     /// will return an error. If the type is not know, it will return `Value::Unknown`
-    pub fn new(value_type: u8, data: u32) -> Result<Self> {
+    pub fn new(value_type: u8, data: u32) -> Result<Self, Error> {
         let value = match value_type {
             TOKEN_TYPE_REFERENCE_ID | TOKEN_TYPE_DYN_REFERENCE => Value::ReferenceId(data),
             TOKEN_TYPE_ATTRIBUTE_REFERENCE_ID | TOKEN_TYPE_DYN_ATTRIBUTE => {
@@ -96,7 +97,10 @@ impl Value {
                         Value::Dimension(formatted)
                     }
                     None => {
-                        return Err(format!("Expected a valid unit index. Got: {}", unit_idx).into())
+                        return Err(format_err!(
+                            "expected a valid unit index, got: {}",
+                            unit_idx
+                        ))
                     }
                 }
             }
@@ -118,7 +122,10 @@ impl Value {
                         Value::Fraction(formatted_fraction)
                     }
                     None => {
-                        return Err(format!("Expected a valid unit index. Got: {}", unit_idx).into())
+                        return Err(format_err!(
+                            "expected a valid unit index, got: {}",
+                            unit_idx
+                        ))
                     }
                 }
             }
diff --git a/src/visitor/mod.rs b/src/visitor/mod.rs
index 543b7fdfb..012d73e99 100644
--- a/src/visitor/mod.rs
+++ b/src/visitor/mod.rs
@@ -1,8 +1,10 @@
 //! Collection of visitors that are fed from chunk iterator
 use std::io::Cursor;
-use chunks::*;
+
+use failure::{Error, ResultExt};
 use byteorder::{LittleEndian, ReadBytesExt};
-use errors::*;
+
+use chunks::*;
 
 mod xml;
 pub mod model;
@@ -32,25 +34,25 @@ pub struct Executor;
 impl Executor {
     /// Given a valid `resources.arsc` file contents, it will call to the proper methods on the
     /// given visitor.
-    pub fn arsc<'a, V: ChunkVisitor<'a>>(buffer: &'a [u8], visitor: &mut V) -> Result<()> {
+    pub fn arsc<'a, V: ChunkVisitor<'a>>(buffer: &'a [u8], visitor: &mut V) -> Result<(), Error> {
         let mut cursor = Cursor::new(buffer);
         let token = cursor
             .read_u16::<LittleEndian>()
-            .chain_err(|| "Error reading first token")?;
+            .context("error reading first token")?;
 
         if token != 0x2 {
-            return Err(format!("File does not start with ARSC token: {:X}", token).into());
+            bail!("file does not start with ARSC token: {:X}", token);
         }
 
         let _header_size = cursor
             .read_u16::<LittleEndian>()
-            .chain_err(|| "Error reading header size")?;
+            .context("error reading header size")?;
         let _chunk_size = cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Error reading chunk size")?;
+            .context("error reading chunk size")?;
         let _package_amount = cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Error reading package amount")?;
+            .context("error reading package amount")?;
         // TODO: Avoid infinite loop
         cursor.set_position(_header_size as u64);
 
@@ -58,7 +60,7 @@ impl Executor {
         let mut origin = Origin::Global;
 
         for c in stream {
-            match c.chain_err(|| "Error reading next chunk")? {
+            match c.context("error reading next chunk")? {
                 Chunk::StringTable(stw) => {
                     visitor.visit_string_table(stw, origin);
                     origin = Origin::next(origin);
@@ -86,26 +88,26 @@ impl Executor {
     pub fn xml<'a, V: ChunkVisitor<'a>>(
         mut cursor: Cursor<&'a [u8]>,
         visitor: &mut V,
-    ) -> Result<()> {
+    ) -> Result<(), Error> {
         let token = cursor
             .read_u16::<LittleEndian>()
-            .chain_err(|| "Error reading first token")?;
+            .context("error reading first token")?;
 
         if token != 0x3 {
-            return Err(format!("Document does not start with XML token: {:X}", token).into());
+            bail!("document does not start with XML token: {:X}", token);
         }
 
         let header_size = cursor
             .read_u16::<LittleEndian>()
-            .chain_err(|| "Error reading header size")?;
+            .context("error reading header size")?;
         let _chunk_size = cursor
             .read_u32::<LittleEndian>()
-            .chain_err(|| "Error reading chunk size")?;
+            .context("error reading chunk size")?;
         cursor.set_position(header_size as u64);
         let stream = ChunkLoaderStream::new(cursor);
 
         for c in stream {
-            match c.chain_err(|| "Error reading next chunk")? {
+            match c.context("error reading next chunk")? {
                 Chunk::StringTable(stw) => {
                     visitor.visit_string_table(stw, Origin::Global);
                 }
diff --git a/src/visitor/model.rs b/src/visitor/model.rs
index acb04c3dd..6cd60e606 100644
--- a/src/visitor/model.rs
+++ b/src/visitor/model.rs
@@ -1,15 +1,17 @@
-use chunks::*;
-use errors::*;
-use std::rc::Rc;
 use std::cell::RefCell;
 use std::collections::HashMap;
-use model::{Entries, Identifier};
-use model::Resources as ResourcesTrait;
+use std::rc::Rc;
+
+use failure::{Error, ResultExt};
+
+use chunks::*;
+use model::owned::Entry;
 use model::Library as LibraryTrait;
-use model::StringTable as StringTableTrait;
 use model::LibraryBuilder;
+use model::Resources as ResourcesTrait;
+use model::StringTable as StringTableTrait;
 use model::TypeSpec as TypeSpecTrait;
-use model::owned::Entry;
+use model::{Entries, Identifier};
 
 use super::ChunkVisitor;
 use super::Origin;
@@ -77,8 +79,8 @@ impl<'a> ChunkVisitor<'a> for ModelVisitor<'a> {
 
                     if set_result.is_none() {
                         error!(
-                            "Could not set the string table because it refers to a \
-                             non-existing package"
+                            "could not set the string table because it refers to a non-existing \
+                             package"
                         );
                     }
                 }
@@ -96,20 +98,15 @@ impl<'a> ChunkVisitor<'a> for ModelVisitor<'a> {
 
             let entries_result = table_type.get_entries();
 
-            if entries_result.is_err() {
-                error!(
-                    "Error visiting table_type: {}",
-                    entries_result.err().unwrap().description()
-                );
-            } else {
-                let ventries = entries_result.unwrap();
-                for e in &ventries {
+            match entries_result {
+                Ok(ventries) => for e in &ventries {
                     let id = mask | e.get_id();
 
                     if !e.is_empty() {
                         entries.insert(id, e.clone());
                     }
-                }
+                },
+                Err(err) => error!("Error visiting table_type: {}", err),
             }
         }
 
@@ -194,9 +191,9 @@ pub struct Library<'a> {
 }
 
 impl<'a> Library<'a> {
-    pub fn new(package: PackageWrapper<'a>) -> Library {
-        Library {
-            package: package,
+    pub fn new(package: PackageWrapper<'a>) -> Self {
+        Self {
+            package,
             specs: Vec::new(),
             string_table: None,
             spec_string_table: None,
@@ -205,7 +202,7 @@ impl<'a> Library<'a> {
         }
     }
 
-    fn get_spec_as_str(&self, spec_id: u32) -> Result<String> {
+    fn get_spec_as_str(&self, spec_id: u32) -> Result<String, Error> {
         if self.specs.get((spec_id - 1) as usize).is_some() {
             if let Some(ref spec_string_table) = self.spec_string_table {
                 if let Ok(spec_str) = spec_string_table.get_string((spec_id - 1) as u32) {
@@ -214,7 +211,7 @@ impl<'a> Library<'a> {
             }
         }
 
-        Err("Could not retrieve spec as string".into())
+        Err(format_err!("could not retrieve spec as string"))
     }
 }
 
@@ -229,12 +226,14 @@ impl<'a> LibraryTrait for Library<'a> {
         key: u32,
         namespace: Option<String>,
         prefix: &str,
-    ) -> Result<String> {
+    ) -> Result<String, Error> {
         let spec_id = id.get_spec() as u32;
         let spec_str = self.get_spec_as_str(spec_id)
-            .chain_err(|| format!("Could not find spec: {}", spec_id))?;
-        let string = self.get_entries_string(key)
-            .chain_err(|| format!("Could not find key {} on entries string table", key))?;
+            .context(format_err!("could not find spec: {}", spec_id))?;
+        let string = self.get_entries_string(key).context(format_err!(
+            "could not find key {} on entries string table",
+            key
+        ))?;
 
         let ending = if spec_str == "attr" {
             string
@@ -248,34 +247,36 @@ impl<'a> LibraryTrait for Library<'a> {
         }
     }
 
-    fn get_entry(&self, id: u32) -> Result<&Entry> {
+    fn get_entry(&self, id: u32) -> Result<&Entry, Error> {
         self.entries
             .get(&id)
-            .ok_or_else(|| "Could not find entry".into())
+            .ok_or_else(|| format_err!("could not find entry"))
     }
 
-    fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>> {
+    fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>, Error> {
         if let Some(ref string_table) = self.entries_string_table {
-            let out_string = string_table
-                .get_string(str_id)
-                .chain_err(|| format!("Could not find string {} on entries string table", str_id))?;
+            let out_string = string_table.get_string(str_id).context(format_err!(
+                "could not find string {} on entries string table",
+                str_id
+            ))?;
 
             return Ok(out_string);
         }
 
-        Err("String not found on entries string table".into())
+        Err(format_err!("string not found on entries string table"))
     }
 
-    fn get_spec_string(&self, str_id: u32) -> Result<Rc<String>> {
+    fn get_spec_string(&self, str_id: u32) -> Result<Rc<String>, Error> {
         if let Some(ref string_table) = self.spec_string_table {
-            let out_string = string_table
-                .get_string(str_id)
-                .chain_err(|| format!("Could not find string {} on spec string table", str_id))?;
+            let out_string = string_table.get_string(str_id).context(format_err!(
+                "could not find string {} on spec string table",
+                str_id
+            ))?;
 
             return Ok(out_string);
         }
 
-        Err("String not found on spec string table".into())
+        Err(format_err!("string not found on spec string table"))
     }
 }
 
diff --git a/src/visitor/xml.rs b/src/visitor/xml.rs
index cf5ef06ba..ed0c215f2 100644
--- a/src/visitor/xml.rs
+++ b/src/visitor/xml.rs
@@ -1,20 +1,15 @@
+use std::cmp::Ordering;
+use std::collections::HashMap;
+use std::rc::Rc;
+
+use failure::{Error, ResultExt};
+
 use chunks::*;
-use model::{Element, ElementContainer, Namespaces};
 use encoder::Xml;
-use visitor::model::Resources;
-use errors::*;
-use model::{NamespaceStart, TagStart};
-use std::rc::Rc;
-use std::collections::HashMap;
-use model::Resources as ResourceTrait;
-use model::Library;
-use model::Identifier;
-use model::AttributeTrait;
-use model::StringTable;
-use model::Value;
-use model::Tag;
 use model::owned::SimpleEntry;
-use std::cmp::Ordering;
+use model::{AttributeTrait, Element, ElementContainer, Identifier, Library, NamespaceStart,
+            Namespaces, Resources as ResourceTrait, StringTable, Tag, TagStart, Value};
+use visitor::model::Resources;
 
 use super::ChunkVisitor;
 use super::Origin;
@@ -30,12 +25,12 @@ pub struct XmlVisitor<'a> {
 
 impl<'a> XmlVisitor<'a> {
     pub fn new(resources: &'a Resources<'a>) -> Self {
-        XmlVisitor {
+        Self {
             main_string_table: None,
             namespaces: Namespaces::default(),
             container: ElementContainer::default(),
             res: Vec::new(),
-            resources: resources,
+            resources,
             namespace_prefixes: Vec::new(),
         }
     }
@@ -61,12 +56,13 @@ impl<'a> XmlVisitor<'a> {
     }
 
     // TODO: Convert to TryInto once it will be stable
-    pub fn into_string(self) -> Result<String> {
+    pub fn into_string(self) -> Result<String, Error> {
         match *self.get_root() {
             Some(ref root) => match *self.get_string_table() {
                 Some(_) => {
-                    return Xml::encode(self.get_namespaces(), root)
-                        .chain_err(|| "Could note encode XML");
+                    let res =
+                        Xml::encode(self.get_namespaces(), root).context("could note encode XML")?;
+                    return Ok(res);
                 }
                 None => {
                     warn!("No string table found");
@@ -77,17 +73,17 @@ impl<'a> XmlVisitor<'a> {
             }
         }
 
-        Err("Could not decode XML".into())
+        Err(format_err!("could not decode XML"))
     }
 
-    fn build_element(&self, tag_start: &XmlTagStartWrapper) -> Result<Element> {
+    fn build_element(&self, tag_start: &XmlTagStartWrapper) -> Result<Element, Error> {
         match self.main_string_table {
             Some(ref string_table) => {
                 let (tag, attributes) = self.get_element_data(string_table, tag_start)
-                    .chain_err(|| "Could not get element data")?;
+                    .context("could not get element data")?;
                 Ok(Element::new(tag, attributes))
             }
-            None => Err("No main string table found!".into()),
+            None => Err(format_err!("no main string table found")),
         }
     }
 
@@ -95,32 +91,32 @@ impl<'a> XmlVisitor<'a> {
         &self,
         string_table: &StringTableCache<StringTableWrapper<'a>>,
         tag_start: &XmlTagStartWrapper,
-    ) -> Result<(Tag, HashMap<String, String>)> {
+    ) -> Result<(Tag, HashMap<String, String>), Error> {
         let name_index = tag_start
             .get_element_name_index()
-            .chain_err(|| "Name index not found")?;
+            .context("name index not found")?;
         let rc_string = string_table
             .get_string(name_index)
-            .chain_err(|| "Element name is not on the string table")?;
+            .context("element name is not on the string table")?;
         let tag = Tag::new(rc_string.clone(), self.namespace_prefixes.clone());
 
         let mut attributes = HashMap::new();
         let num_attributes = tag_start
             .get_attributes_amount()
-            .chain_err(|| "Could not get the amount of attributes")?;
+            .context("could not get the amount of attributes")?;
 
         for i in 0..num_attributes {
             let mut final_name = String::new();
             let current_attribute = tag_start
                 .get_attribute(i)
-                .chain_err(|| format!("Could not read attribute {} ", i))?;
+                .context(format_err!("could not read attribute {} ", i))?;
 
             let namespace_index = current_attribute.get_namespace()?;
             if namespace_index != 0xFFFFFFFF {
                 let namespace = (*string_table.get_string(namespace_index)?).clone();
                 let prefix = self.namespaces
                     .get(&namespace)
-                    .ok_or("Namespace not found")?;
+                    .ok_or(format_err!("namespace not found"))?;
                 final_name.push_str(prefix);
                 final_name.push(':');
             }
@@ -134,11 +130,11 @@ impl<'a> XmlVisitor<'a> {
                 Value::StringReference(index) => (*string_table.get_string(index)?).clone(),
                 Value::ReferenceId(ref id) => {
                     AttributeHelper::resolve_reference(self.resources, *id, "@")
-                        .chain_err(|| "Could not resolve reference")?
+                        .context("could not resolve reference")?
                 }
                 Value::AttributeReferenceId(ref id) => {
                     AttributeHelper::resolve_reference(self.resources, *id, "?")
-                        .chain_err(|| "Could not resolve attribute reference")?
+                        .context("could not resolve attribute reference")?
                 }
                 Value::Integer(ref value) | Value::Flags(ref value) => {
                     let flag_resolution = AttributeHelper::resolve_flags(
@@ -226,7 +222,7 @@ impl AttributeHelper {
         resources: &R,
         id: u32,
         prefix: &str,
-    ) -> Result<String> {
+    ) -> Result<String, Error> {
         let res_id = id;
         let package_id = id.get_package();
 
@@ -237,7 +233,7 @@ impl AttributeHelper {
         let is_main = resources.is_main_package(package_id);
         let package = resources
             .get_package(package_id)
-            .ok_or_else(|| ErrorKind::Msg("Package not found".into()))?;
+            .ok_or(format_err!("package not found"))?;
 
         let entry_key = package.get_entry(res_id).and_then(|e| Ok(e.get_key())).ok();
 
@@ -247,7 +243,7 @@ impl AttributeHelper {
             return package.format_reference(id, key, namespace, prefix);
         }
 
-        Err("Error resolving reference".into())
+        Err(format_err!("error resolving reference"))
     }
 
     pub fn resolve_flags<'a, R: ResourceTrait<'a>, A: AttributeTrait>(
@@ -393,12 +389,13 @@ impl AttributeHelper {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use model::{Library, LibraryBuilder, Resources, StringTable};
-    use model::Entries;
+    use failure::Error;
     use model::owned::{AttributeBuf, ComplexEntry, Entry, SimpleEntry};
-    use visitor::Origin;
+    use model::Entries;
     use model::TypeSpec;
+    use model::{Library, LibraryBuilder, Resources, StringTable};
     use test::FakeStringTable;
+    use visitor::Origin;
 
     struct FakeLibrary {
         entries: Entries,
@@ -441,7 +438,7 @@ mod tests {
             entries.insert((2 << 24) | 5, entry5);
             entries.insert((2 << 24) | 6, entry6);
 
-            FakeLibrary { entries: entries }
+            Self { entries }
         }
     }
 
@@ -456,30 +453,30 @@ mod tests {
             _: u32,
             namespace: Option<String>,
             _: &str,
-        ) -> Result<String> {
+        ) -> Result<String, Error> {
             if id == (1 << 24) | 1 && namespace.is_none() {
                 Ok("reference#1".to_string())
             } else if id == (2 << 24) | 1 && namespace.is_some() {
                 Ok("NS:reference#2".to_string())
             } else {
-                Err("Could not format".into())
+                Err(format_err!("could not format"))
             }
         }
 
-        fn get_entry(&self, id: u32) -> Result<&Entry> {
+        fn get_entry(&self, id: u32) -> Result<&Entry, Error> {
             self.entries
                 .get(&id)
-                .ok_or_else(|| "Could not find entry".into())
+                .ok_or_else(|| format_err!("could not find entry"))
         }
 
-        fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>> {
+        fn get_entries_string(&self, str_id: u32) -> Result<Rc<String>, Error> {
             let st = FakeStringTable;
 
             Ok(st.get_string(str_id)?)
         }
 
-        fn get_spec_string(&self, _: u32) -> Result<Rc<String>> {
-            Err("Sepc string".into())
+        fn get_spec_string(&self, _: u32) -> Result<Rc<String>, Error> {
+            bail!("spec string")
         }
     }
 
@@ -497,20 +494,20 @@ mod tests {
     struct FakeTypeSpec;
 
     impl TypeSpec for FakeTypeSpec {
-        fn get_id(&self) -> Result<u16> {
+        fn get_id(&self) -> Result<u16, Error> {
             Ok(82)
         }
-        fn get_amount(&self) -> Result<u32> {
+        fn get_amount(&self) -> Result<u32, Error> {
             Ok(3)
         }
 
-        fn get_flag(&self, index: u32) -> Result<u32> {
+        fn get_flag(&self, index: u32) -> Result<u32, Error> {
             let flags = vec![0, 4, 16];
 
             flags
                 .get(index as usize)
                 .map(|x| *x)
-                .ok_or("Flag out of bounds".into())
+                .ok_or_else(|| format_err!("flag out of bounds"))
         }
     }
 
@@ -566,7 +563,7 @@ mod tests {
         let reference = AttributeHelper::resolve_reference(&resources, 3 << 24, "prefix");
 
         assert!(reference.is_err());
-        assert_eq!("Package not found", reference.err().unwrap().to_string());
+        assert_eq!("package not found", reference.err().unwrap().to_string());
     }
 
     #[test]
diff --git a/travis-helper.sh b/travis-helper.sh
new file mode 100755
index 000000000..72f9e5eab
--- /dev/null
+++ b/travis-helper.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+action="$1"
+
+if [ "$action" = "install_deps" ]; then
+  # Install rustfmt.
+  if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
+    rustup component add rustfmt-preview
+  fi
+
+  # Install Clippy
+  if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
+    # Install clippy
+    cargo install clippy --force --verbose || true
+  fi
+
+elif [ "$action" = "clippy_run" ]; then
+  if [ "$TRAVIS_RUST_VERSION" == "nightly" ] && cargo clippy --version; then
+    cargo clippy --verbose
+  fi
+
+elif [ "$action" = "fmt_run" ]; then
+  if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
+      cargo fmt --verbose -- --write-mode=diff
+  fi
+
+elif [ "$action" = "upload_code_coverage" ]; then
+  if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
+    wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
+    tar xzf master.tar.gz &&
+    cd kcov-master &&
+    mkdir build &&
+    cd build &&
+    cmake .. &&
+    make &&
+    sudo make install &&
+    cd ../.. &&
+    rm -rf kcov-master &&
+    for file in target/debug/abxml-*[^\.d]; do mkdir -p "target/cov/$(basename $file)"; kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
+    for file in target/debug/lib-*[^\.d]; do mkdir -p "target/cov/$(basename $file)"; kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
+    bash <(curl -s https://codecov.io/bash) &&
+    echo "Uploaded code coverage"
+  fi
+
+elif [ "$action" = "upload_documentation" ]; then
+  if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "develop" ]]; then
+    cargo doc &&
+    echo "<meta http-equiv=refresh content=0;url=abxml/index.html>" > target/doc/index.html &&
+    git clone https://github.com/davisp/ghp-import.git &&
+    ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&
+    echo "Uploaded documentation"
+  fi
+
+fi
+
+exit $?


Test patch:
diff --git a/src/test.rs b/src/test.rs
index 8d4bc9c29..3b558f867 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -1,19 +1,17 @@
+use failure::Error;
+
 use chunks::*;
+use model;
+use std::rc::Rc;
 use visitor::ChunkVisitor;
 use visitor::Origin;
-use std::rc::Rc;
-use errors::*;
-use model;
 
+#[derive(Default)]
 pub struct CounterChunkVisitor {
     count: u32,
 }
 
 impl CounterChunkVisitor {
-    pub fn new() -> CounterChunkVisitor {
-        CounterChunkVisitor { count: 0 }
-    }
-
     pub fn get_count(&self) -> u32 {
         self.count
     }
@@ -85,7 +83,7 @@ impl model::StringTable for FakeStringTable {
         0
     }
 
-    fn get_string(&self, idx: u32) -> Result<Rc<String>> {
+    fn get_string(&self, idx: u32) -> Result<Rc<String>, Error> {
         match idx {
             0 => Ok(Rc::new("Zero".to_string())),
             11 => Ok(Rc::new("Ones".to_string())),
@@ -95,7 +93,7 @@ impl model::StringTable for FakeStringTable {
             123 => Ok(Rc::new("center".to_string())),
             456 => Ok(Rc::new("left".to_string())),
             789 => Ok(Rc::new("right".to_string())),
-            _ => Err("Index out of bounds".into()),
+            _ => bail!("index out of bounds"),
         }
     }
 }
diff --git a/tests/lib.rs b/tests/lib.rs
index bb5171239..bd4ed1453 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -2,7 +2,7 @@ extern crate abxml;
 
 use abxml::decoder::Decoder;
 use abxml::model::builder::Xml;
-use abxml::model::owned::{XmlTagStartBuf, XmlTagEndBuf, StringTableBuf, AttributeBuf};
+use abxml::model::owned::{AttributeBuf, StringTableBuf, XmlTagEndBuf, XmlTagStartBuf};
 
 #[test]
 fn it_can_generate_a_decoder_from_a_buffer() {