Skip to content

Commit

Permalink
Merge pull request #34 from afdw/master
Browse files Browse the repository at this point in the history
Add support for unions without typedefs
  • Loading branch information
alexcrichton committed Jul 16, 2018
2 parents 5c53723 + 8078823 commit bf780a0
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 6 deletions.
45 changes: 39 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,25 @@ pub struct TestGenerator {
skip_type: Box<Fn(&str) -> bool>,
skip_struct: Box<Fn(&str) -> bool>,
field_name: Box<Fn(&str, &str) -> String>,
type_name: Box<Fn(&str, bool) -> String>,
type_name: Box<Fn(&str, bool, bool) -> String>,
fn_cname: Box<Fn(&str, Option<&str>) -> String>,
}

struct StructFinder {
structs: HashSet<String>,
}

struct UnionFinder {
unions: HashSet<String>,
}

struct Generator<'a> {
target: &'a str,
rust: Box<Write>,
c: Box<Write>,
sh: &'a SpanHandler,
structs: HashSet<String>,
unions: HashSet<String>,
files: HashSet<String>,
abi: Abi,
tests: Vec<String>,
Expand Down Expand Up @@ -116,8 +121,14 @@ impl TestGenerator {
skip_field: Box::new(|_, _| false),
skip_field_type: Box::new(|_, _| false),
fn_cname: Box::new(|a, _| a.to_string()),
type_name: Box::new(|f, is_struct| {
if is_struct {format!("struct {}", f)} else {f.to_string()}
type_name: Box::new(|f, is_struct, is_union| {
if is_struct {
format!("struct {}", f)
} else if is_union {
format!("union {}", f)
} else {
f.to_string()
}
}),
}
}
Expand Down Expand Up @@ -284,15 +295,15 @@ impl TestGenerator {
/// use ctest::TestGenerator;
///
/// let mut cfg = TestGenerator::new();
/// cfg.type_name(|ty, is_struct| {
/// cfg.type_name(|ty, is_struct, is_union| {
/// if is_struct {
/// format!("{}_t", ty)
/// } else {
/// ty.to_string()
/// }
/// });
pub fn type_name<F>(&mut self, f: F) -> &mut TestGenerator
where F: Fn(&str, bool) -> String + 'static
where F: Fn(&str, bool, bool) -> String + 'static
{
self.type_name = Box::new(f);
self
Expand Down Expand Up @@ -668,12 +679,20 @@ impl TestGenerator {
};
visit::walk_crate(&mut structs, &krate);

// Probe the crate to find all unions (used to convert type names to
// names in C).
let mut unions = UnionFinder {
unions: HashSet::new(),
};
visit::walk_crate(&mut unions, &krate);

let mut gen = Generator {
target: &target,
rust: Box::new(rust_out),
c: Box::new(c_out),
sh: &sess.span_diagnostic,
structs: structs.structs,
unions: unions.unions,
abi: Abi::C,
tests: Vec::new(),
files: HashSet::new(),
Expand Down Expand Up @@ -879,7 +898,7 @@ impl<'a> Generator<'a> {
"i32" => "int32_t".to_string(),
"i64" => "int64_t".to_string(),

s => (self.opts.type_name)(s, self.structs.contains(s)),
s => (self.opts.type_name)(s, self.structs.contains(s), self.unions.contains(s)),
}
}

Expand Down Expand Up @@ -1463,6 +1482,20 @@ impl<'v> Visitor<'v> for StructFinder {
fn visit_mac(&mut self, _mac: &'v ast::Mac) { }
}

impl<'v> Visitor<'v> for UnionFinder {
fn visit_item(&mut self, i: &'v ast::Item) {
match i.node {
ast::ItemKind::Union(..) => {
self.unions.insert(i.ident.to_string());
}

_ => {}
}
visit::walk_item(self, i)
}
fn visit_mac(&mut self, _mac: &'v ast::Mac) { }
}

struct MyResolver<'a> {
parse_sess: &'a ParseSess,
id: usize,
Expand Down
16 changes: 16 additions & 0 deletions testcrate/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,25 @@ fn main() {
.header("t1.h")
.include("src")
.fn_cname(|a, b| b.unwrap_or(a).to_string())
.type_name(move |ty, is_struct, is_union|
match ty {
"T1Union" => ty.to_string(),
t if is_struct => format!("struct {}", t),
t if is_union => format!("union {}", t),
t => t.to_string(),
}
)
.generate("src/t1.rs", "t1gen.rs");
ctest::TestGenerator::new()
.header("t2.h")
.include("src")
.type_name(move |ty, is_struct, is_union|
match ty {
"T2Union" => ty.to_string(),
t if is_struct => format!("struct {}", t),
t if is_union => format!("union {}", t),
t => t.to_string(),
}
)
.generate("src/t2.rs", "t2gen.rs");
}
9 changes: 9 additions & 0 deletions testcrate/src/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ typedef union {
uint32_t b;
} T1Union;

union T1NoTypedefUnion {
uint64_t a;
uint32_t b;
};

struct T1StructWithUnion {
union T1NoTypedefUnion u;
};

void T1a(void);
void* T1b(void);
void* T1c(void*);
Expand Down
11 changes: 11 additions & 0 deletions testcrate/src/t1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ pub union T1Union {
pub b: u32,
}

#[repr(C)]
pub union T1NoTypedefUnion {
pub a: u64,
pub b: u32,
}

#[repr(C)]
pub struct T1StructWithUnion {
pub u: T1NoTypedefUnion,
}

i! {
pub const T1C: u32 = 4;
}
Expand Down

0 comments on commit bf780a0

Please sign in to comment.