summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-03-27 12:15:33 -0700
committerGitHub <noreply@github.com>2017-03-27 12:15:33 -0700
commit7ed7c2492fbda2e25fe84be0696341288998bd8b (patch)
tree77d4166045932df4b7899d4311a4a1ba58ece234
parent3cb681918a8ea1f670516e0edfca97ab81ef767a (diff)
parent63de9486e8e1a2d2987c93a7fedd766bf8c52b78 (diff)
Auto merge of #601 - luser:string-input, r=emilio
Add a `Builder::header_contents` method to allow passing source code as a string to a Builder Currently the Builder API requires input as header files on disk. This allows passing C source directly to clang using the existing UnsavedFile struct. I'm going to take a shot at implementing a webapp that lets users paste in C source and get the bindgen output. It would make life easier if I didn't have to write the source out to a temp file. This patch allows passing the source in as a `&str`. I wasn't quite sure where to put the new test, but it seems to work in tests.rs.
-rw-r--r--src/clang.rs13
-rw-r--r--src/ir/context.rs2
-rw-r--r--src/lib.rs16
-rw-r--r--tests/tests.rs18
4 files changed, 46 insertions, 3 deletions
diff --git a/src/clang.rs b/src/clang.rs
index fc7950dc..ee422745 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -1409,7 +1409,9 @@ impl Drop for Diagnostic {
/// A file which has not been saved to disk.
pub struct UnsavedFile {
x: CXUnsavedFile,
- name: CString,
+ /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
+ /// `CXUnsavedFile`.
+ pub name: CString,
contents: CString,
}
@@ -1431,6 +1433,15 @@ impl UnsavedFile {
}
}
+impl fmt::Debug for UnsavedFile {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt,
+ "UnsavedFile(name: {:?}, contents: {:?})",
+ self.name,
+ self.contents)
+ }
+}
+
/// Convert a cursor kind into a static string.
pub fn kind_to_str(x: CXCursorKind) -> String {
unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 4a6785b1..c95d5179 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -182,7 +182,7 @@ impl<'ctx> BindgenContext<'ctx> {
clang::TranslationUnit::parse(&index,
"",
&options.clang_args,
- &[],
+ &options.input_unsaved_files,
parse_options)
.expect("TranslationUnit::parse failed");
diff --git a/src/lib.rs b/src/lib.rs
index 433198b0..8f838c15 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -175,6 +175,14 @@ impl Builder {
self
}
+ /// Add `contents` as an input C/C++ header named `name`.
+ ///
+ /// The file `name` will be added to the clang arguments.
+ pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
+ self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents));
+ self
+ }
+
/// Set the output graphviz file.
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
let path = path.into();
@@ -573,6 +581,9 @@ pub struct BindgenOptions {
/// The input header file.
pub input_header: Option<String>,
+ /// Unsaved files for input.
+ pub input_unsaved_files: Vec<clang::UnsavedFile>,
+
/// Generate a dummy C/C++ file that includes the header and has dummy uses
/// of all types defined therein. See the `uses` module for more.
pub dummy_uses: Option<String>,
@@ -662,6 +673,7 @@ impl Default for BindgenOptions {
raw_lines: vec![],
clang_args: vec![],
input_header: None,
+ input_unsaved_files: vec![],
dummy_uses: None,
parse_callbacks: None,
codegen_config: CodegenConfig::all(),
@@ -754,6 +766,10 @@ impl<'ctx> Bindings<'ctx> {
options.clang_args.push(h.clone())
}
+ for f in options.input_unsaved_files.iter() {
+ options.clang_args.push(f.name.to_str().unwrap().to_owned())
+ }
+
let mut context = BindgenContext::new(options);
try!(parse(&mut context));
diff --git a/tests/tests.rs b/tests/tests.rs
index 6b69e0d4..84b5e076 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -3,7 +3,7 @@ extern crate diff;
extern crate bindgen;
extern crate shlex;
-use bindgen::Builder;
+use bindgen::{Builder, builder};
use std::fs;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
use std::path::PathBuf;
@@ -144,3 +144,19 @@ macro_rules! test_header {
// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
+
+#[test]
+fn test_header_contents() {
+ let bindings = builder()
+ .header_contents("test.h", "int foo(const char* a);")
+ .no_unstable_rust()
+ .generate()
+ .unwrap()
+ .to_string();
+ assert_eq!(bindings, "/* automatically generated by rust-bindgen */
+
+extern \"C\" {
+ pub fn foo(a: *const ::std::os::raw::c_schar) -> ::std::os::raw::c_int;
+}
+");
+}