Skip to content

Commit e00a8a1

Browse files
committed
Union fields.
1 parent c88a37b commit e00a8a1

File tree

1 file changed

+82
-18
lines changed

1 file changed

+82
-18
lines changed

src/codegen/mod.rs

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -511,25 +511,23 @@ impl CodeGenerator for CompInfo {
511511
}
512512
}
513513

514-
if !is_union {
515-
let ty = field.ty().to_rust_ty(ctx);
516-
517-
let ty = if is_union {
518-
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
519-
} else {
520-
ty
521-
};
522-
523-
let mut attrs = vec![];
524-
if let Some(comment) = field.comment() {
525-
attrs.push(doc!(comment));
526-
}
514+
let ty = field.ty().to_rust_ty(ctx);
515+
516+
let ty = if is_union {
517+
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
518+
} else {
519+
ty
520+
};
527521

528-
let field = StructFieldBuilder::named(field.name()).pub_()
529-
.with_attrs(attrs)
530-
.build_ty(ty);
531-
fields.push(field);
522+
let mut attrs = vec![];
523+
if let Some(comment) = field.comment() {
524+
attrs.push(doc!(comment));
532525
}
526+
527+
let field = StructFieldBuilder::named(field.name()).pub_()
528+
.with_attrs(attrs)
529+
.build_ty(ty);
530+
fields.push(field);
533531
}
534532

535533
if is_union {
@@ -945,14 +943,80 @@ impl CodeGenerator for Function {
945943

946944
pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
947945
context.gen(|context| {
948-
let mut result = vec![];
946+
let mut result = CodegenResult::new();
949947
for (item_id, item) in context.items() {
950948
// Non-toplevel item parents are the responsible one for generating
951949
// them.
952950
if item.is_toplevel(context) {
953951
item.codegen(context, &mut result, &());
954952
}
955953
}
954+
let saw_union = result.saw_union;
955+
let mut result = result.items;
956+
if saw_union {
957+
utils::prepend_union_types(context, &mut result);
958+
}
956959
result
957960
})
958961
}
962+
963+
mod utils {
964+
use ir::context::BindgenContext;
965+
use syntax::ast;
966+
use syntax::ptr::P;
967+
use std::mem;
968+
969+
pub fn prepend_union_types(ctx: &BindgenContext, result: &mut Vec<P<ast::Item>>) {
970+
use std::mem;
971+
let union_field_decl = quote_item!(ctx.ext_cx(),
972+
#[derive(Copy, Debug)]
973+
#[repr(C)]
974+
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
975+
).unwrap();
976+
977+
let union_field_impl = quote_item!(&ctx.ext_cx(),
978+
impl<T> __BindgenUnionField<T> {
979+
#[inline]
980+
pub fn new() -> Self {
981+
__BindgenUnionField(::std::marker::PhantomData)
982+
}
983+
984+
#[inline]
985+
pub unsafe fn as_ref(&self) -> &T {
986+
::std::mem::transmute(self)
987+
}
988+
989+
#[inline]
990+
pub unsafe fn as_mut(&mut self) -> &mut T {
991+
::std::mem::transmute(self)
992+
}
993+
}
994+
).unwrap();
995+
996+
let union_field_default_impl = quote_item!(&ctx.ext_cx(),
997+
impl<T> ::std::default::Default for __BindgenUnionField<T> {
998+
#[inline]
999+
fn default() -> Self {
1000+
Self::new()
1001+
}
1002+
}
1003+
).unwrap();
1004+
1005+
let union_field_clone_impl = quote_item!(&ctx.ext_cx(),
1006+
impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
1007+
#[inline]
1008+
fn clone(&self) -> Self {
1009+
Self::new()
1010+
}
1011+
}
1012+
).unwrap();
1013+
1014+
let items = vec![
1015+
union_field_decl, union_field_impl,
1016+
union_field_default_impl, union_field_clone_impl
1017+
];
1018+
1019+
let old_items = mem::replace(result, items);
1020+
result.extend(old_items.into_iter());
1021+
}
1022+
}

0 commit comments

Comments
 (0)