Add an Error type
This commit is contained in:
@@ -6,6 +6,7 @@ use std::path;
|
||||
|
||||
use bindgen::cargo::Cargo;
|
||||
use bindgen::config::{Braces, Config, Language};
|
||||
use bindgen::error::Error;
|
||||
use bindgen::library::Library;
|
||||
use bindgen::bindings::Bindings;
|
||||
use bindgen::parser::{self, Parse};
|
||||
@@ -200,7 +201,7 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn generate(self) -> Result<Bindings, String> {
|
||||
pub fn generate(self) -> Result<Bindings, Error> {
|
||||
let mut result = Parse::new();
|
||||
|
||||
if self.std_types {
|
||||
|
||||
@@ -8,6 +8,7 @@ use bindgen::cargo::cargo_expand;
|
||||
use bindgen::cargo::cargo_lock::{self, Lock};
|
||||
use bindgen::cargo::cargo_metadata::{self, Metadata};
|
||||
use bindgen::cargo::cargo_toml;
|
||||
use bindgen::error::Error;
|
||||
|
||||
/// Parse a dependency string used in Cargo.lock
|
||||
fn parse_dep_string(dep_string: &str) -> (&str, &str) {
|
||||
@@ -40,7 +41,7 @@ impl Cargo {
|
||||
crate_dir: &Path,
|
||||
binding_crate_name: Option<&str>,
|
||||
use_cargo_lock: bool,
|
||||
) -> Result<Cargo, String> {
|
||||
) -> Result<Cargo, Error> {
|
||||
let toml_path = crate_dir.join("Cargo.toml");
|
||||
let lock_path = crate_dir.join("Cargo.lock");
|
||||
|
||||
@@ -48,7 +49,7 @@ impl Cargo {
|
||||
match cargo_lock::lock(&lock_path) {
|
||||
Ok(lock) => Some(lock),
|
||||
Err(x) => {
|
||||
warn!("couldn't load lock file {:?}: {:?}", lock_path, x);
|
||||
warn!("Couldn't load lock file {:?}: {:?}", lock_path, x);
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -56,15 +57,13 @@ impl Cargo {
|
||||
None
|
||||
};
|
||||
let metadata = cargo_metadata::metadata(&toml_path).map_err(|x| {
|
||||
format!(
|
||||
"couldn't execute `cargo metadata` with manifest {:?}: {:?}",
|
||||
toml_path, x
|
||||
)
|
||||
Error::CargoMetadata(toml_path.to_str().unwrap().to_owned(), x)
|
||||
})?;
|
||||
|
||||
// Use the specified binding crate name or infer it from the manifest
|
||||
let manifest = cargo_toml::manifest(&toml_path)
|
||||
.map_err(|_| format!("couldn't load {:?}.", toml_path))?;
|
||||
let manifest = cargo_toml::manifest(&toml_path).map_err(|x| {
|
||||
Error::CargoToml(toml_path.to_str().unwrap().to_owned(), x)
|
||||
})?;
|
||||
|
||||
let binding_crate_name =
|
||||
binding_crate_name.map_or(manifest.package.name.clone(), |x| x.to_owned());
|
||||
@@ -191,7 +190,7 @@ impl Cargo {
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn expand_crate(&self, package: &PackageRef) -> Result<String, String> {
|
||||
pub(crate) fn expand_crate(&self, package: &PackageRef) -> Result<String, cargo_expand::Error> {
|
||||
cargo_expand::expand(&self.manifest_path, &package.name, &package.version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,39 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::str::from_utf8;
|
||||
use std::str::{Utf8Error, from_utf8};
|
||||
|
||||
extern crate tempdir;
|
||||
use self::tempdir::TempDir;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Possible errors that can occur during `rustc --pretty=expanded`.
|
||||
pub enum Error {
|
||||
/// Error during creation of temporary directory
|
||||
Io(io::Error),
|
||||
/// Output of `cargo metadata` was not valid utf8
|
||||
Utf8(Utf8Error),
|
||||
/// Error during execution of `cargo rustc --pretty=expanded`
|
||||
Compile(String),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<Utf8Error> for Error {
|
||||
fn from(err: Utf8Error) -> Self {
|
||||
Error::Utf8(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Use rustc to expand and pretty print the crate into a single file,
|
||||
/// removing any macros in the process.
|
||||
pub fn expand(manifest_path: &Path, crate_name: &str, version: &str) -> Result<String, String> {
|
||||
pub fn expand(manifest_path: &Path, crate_name: &str, version: &str) -> Result<String, Error> {
|
||||
let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
|
||||
let run = |target_dir: &Path| {
|
||||
let mut cmd = Command::new(cargo);
|
||||
@@ -27,13 +50,13 @@ pub fn expand(manifest_path: &Path, crate_name: &str, version: &str) -> Result<S
|
||||
cmd.arg("-Z");
|
||||
cmd.arg("unstable-options");
|
||||
cmd.arg("--pretty=expanded");
|
||||
let output = cmd.output().unwrap();
|
||||
let output = cmd.output()?;
|
||||
|
||||
let src = from_utf8(&output.stdout).unwrap().to_owned();
|
||||
let error = from_utf8(&output.stderr).unwrap().to_owned();
|
||||
let src = from_utf8(&output.stdout)?.to_owned();
|
||||
let error = from_utf8(&output.stderr)?.to_owned();
|
||||
|
||||
if src.len() == 0 {
|
||||
Err(error)
|
||||
Err(Error::Compile(error))
|
||||
} else {
|
||||
Ok(src)
|
||||
}
|
||||
@@ -44,8 +67,7 @@ pub fn expand(manifest_path: &Path, crate_name: &str, version: &str) -> Result<S
|
||||
} else {
|
||||
// Create a temp directory to use as a target dir for cargo expand, for
|
||||
// hygenic purposes.
|
||||
let target_dir = TempDir::new("cbindgen-expand")
|
||||
.map_err(|_| format!("couldn't create a temp target directory"))?;
|
||||
let target_dir = TempDir::new("cbindgen-expand")?;
|
||||
|
||||
run(target_dir.path())
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
mod cargo;
|
||||
mod cargo_expand;
|
||||
mod cargo_lock;
|
||||
mod cargo_metadata;
|
||||
mod cargo_toml;
|
||||
pub(crate) mod cargo_expand;
|
||||
pub(crate) mod cargo_lock;
|
||||
pub(crate) mod cargo_metadata;
|
||||
pub(crate) mod cargo_toml;
|
||||
|
||||
pub(crate) use self::cargo::*;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub use bindgen::cargo::cargo_metadata::Error as CargoMetadataError;
|
||||
pub use bindgen::cargo::cargo_toml::Error as CargoTomlError;
|
||||
pub use bindgen::cargo::cargo_expand::Error as CargoExpandError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
CargoMetadata(String, CargoMetadataError),
|
||||
CargoToml(String, CargoTomlError),
|
||||
CargoExpand(String, CargoExpandError),
|
||||
ParseSyntaxError{crate_name: String, src_path: String, message: String},
|
||||
ParseCannotOpenFile{crate_name: String, src_path: String},
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Error::CargoMetadata(ref path, ref error) => {
|
||||
write!(f, "Couldn't execute `cargo metadata` with manifest {:?}: {:?}", path, error)
|
||||
}
|
||||
&Error::CargoToml(ref path, ref error) => {
|
||||
write!(f, "Couldn't load manifest file {:?}: {:?}", path, error)
|
||||
}
|
||||
&Error::CargoExpand(ref crate_name, ref error) => {
|
||||
write!(f, "Parsing crate `{}`: couldn't run `cargo rustc --pretty=expanded`: {:?}", crate_name, error)
|
||||
}
|
||||
&Error::ParseSyntaxError{ref crate_name, ref src_path, ref message} => {
|
||||
write!(f, "Parsing crate `{}`:`{}`:\n{}", crate_name, src_path, message)
|
||||
}
|
||||
&Error::ParseCannotOpenFile{ref crate_name, ref src_path} => {
|
||||
write!(f, "Parsing crate `{}`: cannot open file `{}`.", crate_name, src_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use std::mem;
|
||||
use bindgen::bindings::Bindings;
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::error::Error;
|
||||
use bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap};
|
||||
use bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union};
|
||||
use bindgen::monomorph::Monomorphs;
|
||||
@@ -50,7 +51,7 @@ impl Library {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(mut self) -> Result<Bindings, String> {
|
||||
pub fn generate(mut self) -> Result<Bindings, Error> {
|
||||
self.functions.sort_by(|x, y| x.name.cmp(&y.name));
|
||||
|
||||
self.transfer_annotations();
|
||||
|
||||
@@ -40,6 +40,7 @@ mod cargo;
|
||||
mod cdecl;
|
||||
mod config;
|
||||
mod dependencies;
|
||||
mod error;
|
||||
mod ir;
|
||||
mod library;
|
||||
mod mangle;
|
||||
@@ -55,3 +56,4 @@ pub(crate) use self::cargo::*;
|
||||
pub use self::config::*;
|
||||
pub use self::bindings::Bindings;
|
||||
pub use self::builder::Builder;
|
||||
pub use self::error::Error;
|
||||
|
||||
+31
-22
@@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
|
||||
use syn;
|
||||
|
||||
use bindgen::cargo::{Cargo, PackageRef};
|
||||
use bindgen::error::Error;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams};
|
||||
use bindgen::ir::{ItemMap, OpaqueItem, Static, Struct, Typedef, Union};
|
||||
use bindgen::utilities::{SynAbiHelpers, SynItemHelpers};
|
||||
@@ -23,7 +24,7 @@ const STD_CRATES: &'static [&'static str] = &[
|
||||
"proc_macro",
|
||||
];
|
||||
|
||||
type ParseResult = Result<Parse, String>;
|
||||
type ParseResult = Result<Parse, Error>;
|
||||
|
||||
/// Parses a single rust source file, not following `mod` or `extern crate`.
|
||||
pub fn parse_src(src_file: &Path) -> ParseResult {
|
||||
@@ -128,7 +129,7 @@ impl Parser {
|
||||
return !STD_CRATES.contains(&pkg_name.as_ref()) && !self.exclude.contains(&pkg_name);
|
||||
}
|
||||
|
||||
fn parse_crate(&mut self, pkg: &PackageRef) -> Result<(), String> {
|
||||
fn parse_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
|
||||
assert!(self.lib.is_some());
|
||||
self.parsed_crates.insert(pkg.name.clone());
|
||||
|
||||
@@ -153,14 +154,22 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expand_crate(&mut self, pkg: &PackageRef) -> Result<(), String> {
|
||||
fn parse_expand_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
|
||||
assert!(self.lib.is_some());
|
||||
|
||||
let mod_parsed = {
|
||||
if !self.cache_expanded_crate.contains_key(&pkg.name) {
|
||||
let s = self.lib.as_ref().unwrap().expand_crate(pkg)?;
|
||||
let s = self.lib.as_ref().unwrap().expand_crate(pkg)
|
||||
.map_err(|x| Error::CargoExpand(
|
||||
pkg.name.clone(),
|
||||
x
|
||||
))?;
|
||||
let i = syn::parse_crate(&s)
|
||||
.map_err(|msg| format!("Parsing crate `{}`:\n{}.", pkg.name, msg))?;
|
||||
.map_err(|msg| Error::ParseSyntaxError{
|
||||
crate_name: pkg.name.clone(),
|
||||
src_path: "".to_owned(),
|
||||
message: msg,
|
||||
})?;
|
||||
self.cache_expanded_crate.insert(pkg.name.clone(), i.items);
|
||||
}
|
||||
|
||||
@@ -174,7 +183,7 @@ impl Parser {
|
||||
&mut self,
|
||||
pkg: &PackageRef,
|
||||
items: &Vec<syn::Item>,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<(), Error> {
|
||||
self.out.load_syn_crate_mod(
|
||||
&self.binding_crate_name,
|
||||
&pkg.name,
|
||||
@@ -193,11 +202,7 @@ impl Parser {
|
||||
if let &Some(ref inline_items) = inline_items {
|
||||
self.process_expanded_mod(pkg, inline_items)?;
|
||||
} else {
|
||||
error!(
|
||||
"Parsing crate `{}`: external mod found in expanded source, \
|
||||
this shouldn't be possible.",
|
||||
pkg.name
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
if cfg.is_some() {
|
||||
@@ -246,7 +251,7 @@ impl Parser {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_mod(&mut self, pkg: &PackageRef, mod_path: &Path) -> Result<(), String> {
|
||||
fn parse_mod(&mut self, pkg: &PackageRef, mod_path: &Path) -> Result<(), Error> {
|
||||
let mod_parsed = {
|
||||
let owned_mod_path = mod_path.to_path_buf();
|
||||
|
||||
@@ -261,20 +266,24 @@ impl Parser {
|
||||
|
||||
let mut s = String::new();
|
||||
let mut f = File::open(mod_path).map_err(|_| {
|
||||
format!(
|
||||
"Parsing crate `{}`: cannot open file `{:?}`.",
|
||||
pkg.name, mod_path
|
||||
)
|
||||
Error::ParseCannotOpenFile{
|
||||
crate_name: pkg.name.clone(),
|
||||
src_path: mod_path.to_str().unwrap().to_owned(),
|
||||
}
|
||||
})?;
|
||||
f.read_to_string(&mut s).map_err(|_| {
|
||||
format!(
|
||||
"Parsing crate `{}`: cannot open file `{:?}`.",
|
||||
pkg.name, mod_path
|
||||
)
|
||||
Error::ParseCannotOpenFile{
|
||||
crate_name: pkg.name.clone(),
|
||||
src_path: mod_path.to_str().unwrap().to_owned(),
|
||||
}
|
||||
})?;
|
||||
|
||||
let i = syn::parse_crate(&s).map_err(|msg| {
|
||||
format!("Parsing crate `{}`:\n{}.", pkg.name, limit_string(&msg))
|
||||
Error::ParseSyntaxError{
|
||||
crate_name: pkg.name.clone(),
|
||||
src_path: "".to_owned(),
|
||||
message: limit_string(&msg).to_owned(),
|
||||
}
|
||||
})?;
|
||||
|
||||
self.cache_src.insert(owned_mod_path.clone(), i.items);
|
||||
@@ -293,7 +302,7 @@ impl Parser {
|
||||
pkg: &PackageRef,
|
||||
mod_dir: &Path,
|
||||
items: &Vec<syn::Item>,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<(), Error> {
|
||||
self.out.load_syn_crate_mod(
|
||||
&self.binding_crate_name,
|
||||
&pkg.name,
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ use std::path::Path;
|
||||
|
||||
/// A utility function for build scripts to generate bindings for a crate, using
|
||||
/// a `cbindgen.toml` if it exists.
|
||||
pub fn generate<P: AsRef<Path>>(crate_dir: P) -> Result<Bindings, String> {
|
||||
pub fn generate<P: AsRef<Path>>(crate_dir: P) -> Result<Bindings, Error> {
|
||||
let config = Config::from_root_or_default(crate_dir.as_ref());
|
||||
|
||||
generate_with_config(crate_dir, config)
|
||||
@@ -29,7 +29,7 @@ pub fn generate<P: AsRef<Path>>(crate_dir: P) -> Result<Bindings, String> {
|
||||
pub fn generate_with_config<P: AsRef<Path>>(
|
||||
crate_dir: P,
|
||||
config: Config,
|
||||
) -> Result<Bindings, String> {
|
||||
) -> Result<Bindings, Error> {
|
||||
Builder::new()
|
||||
.with_config(config)
|
||||
.with_crate(crate_dir)
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ use clap::{App, Arg, ArgMatches};
|
||||
mod logging;
|
||||
mod bindgen;
|
||||
|
||||
use bindgen::{Bindings, Builder, Cargo, Config, Language};
|
||||
use bindgen::{Bindings, Builder, Cargo, Config, Error, Language};
|
||||
|
||||
fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
// We allow specifying a language to override the config default. This is
|
||||
@@ -43,7 +43,7 @@ fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_bindings<'a>(input: &Path, matches: &ArgMatches<'a>) -> Result<Bindings, String> {
|
||||
fn load_bindings<'a>(input: &Path, matches: &ArgMatches<'a>) -> Result<Bindings, Error> {
|
||||
// If a file is specified then we load it as a single source
|
||||
if !input.is_dir() {
|
||||
// Load any config specified or search in the input directory
|
||||
|
||||
Reference in New Issue
Block a user