diff --git a/src/bindgen/ir/annotation.rs b/src/bindgen/ir/annotation.rs index 6625fe1..79e4233 100644 --- a/src/bindgen/ir/annotation.rs +++ b/src/bindgen/ir/annotation.rs @@ -2,6 +2,7 @@ * 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::collections::hash_map::Entry; use std::collections::HashMap; use std::str::FromStr; @@ -115,8 +116,11 @@ impl AnnotationSet { }) } - pub fn add(&mut self, name: &str, value: AnnotationValue) { - self.annotations.insert(name.to_string(), value); + /// Adds an annotation value if none is specified. + pub fn add_default(&mut self, name: &str, value: AnnotationValue) { + if let Entry::Vacant(e) = self.annotations.entry(name.to_string()) { + e.insert(value); + } } pub fn list(&self, name: &str) -> Option> { diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 9437097..ae846f0 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -145,7 +145,7 @@ impl EnumVariant { let variant_cfg = Cfg::append(mod_cfg, Cfg::load(&variant.attrs)); let mut annotations = AnnotationSet::load(&variant.attrs)?; if let Some(b) = enum_annotations.bool("derive-ostream") { - annotations.add("derive-ostream", AnnotationValue::Bool(b)); + annotations.add_default("derive-ostream", AnnotationValue::Bool(b)); } let body = match variant.fields { syn::Fields::Unit => VariantBody::Empty(annotations), diff --git a/tests/expectations/both/derive_ostream.c b/tests/expectations/both/derive_ostream.c index 9508230..f90d0a8 100644 --- a/tests/expectations/both/derive_ostream.c +++ b/tests/expectations/both/derive_ostream.c @@ -72,4 +72,22 @@ typedef struct H { }; } H; -void root(A a, B b, C c, D d, F f, H h); +enum I_Tag { + ThereAgain, + SomethingElse, +}; +typedef uint8_t I_Tag; + +typedef struct ThereAgain_Body { + uint8_t x; + int16_t y; +} ThereAgain_Body; + +typedef struct I { + I_Tag tag; + union { + ThereAgain_Body there_again; + }; +} I; + +void root(A a, B b, C c, D d, F f, H h, I i); diff --git a/tests/expectations/both/derive_ostream.compat.c b/tests/expectations/both/derive_ostream.compat.c index 8b1f191..35b8996 100644 --- a/tests/expectations/both/derive_ostream.compat.c +++ b/tests/expectations/both/derive_ostream.compat.c @@ -90,11 +90,35 @@ typedef struct H { }; } H; +enum I_Tag +#ifdef __cplusplus + : uint8_t +#endif // __cplusplus + { + ThereAgain, + SomethingElse, +}; +#ifndef __cplusplus +typedef uint8_t I_Tag; +#endif // __cplusplus + +typedef struct ThereAgain_Body { + uint8_t x; + int16_t y; +} ThereAgain_Body; + +typedef struct I { + I_Tag tag; + union { + ThereAgain_Body there_again; + }; +} I; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(A a, B b, C c, D d, F f, H h); +void root(A a, B b, C c, D d, F f, H h, I i); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/derive_ostream.c b/tests/expectations/derive_ostream.c index 210590f..69b76e1 100644 --- a/tests/expectations/derive_ostream.c +++ b/tests/expectations/derive_ostream.c @@ -72,4 +72,22 @@ typedef struct { }; } H; -void root(A a, B b, C c, D d, F f, H h); +enum I_Tag { + ThereAgain, + SomethingElse, +}; +typedef uint8_t I_Tag; + +typedef struct { + uint8_t x; + int16_t y; +} ThereAgain_Body; + +typedef struct { + I_Tag tag; + union { + ThereAgain_Body there_again; + }; +} I; + +void root(A a, B b, C c, D d, F f, H h, I i); diff --git a/tests/expectations/derive_ostream.compat.c b/tests/expectations/derive_ostream.compat.c index 6e20467..59bc476 100644 --- a/tests/expectations/derive_ostream.compat.c +++ b/tests/expectations/derive_ostream.compat.c @@ -90,11 +90,35 @@ typedef struct { }; } H; +enum I_Tag +#ifdef __cplusplus + : uint8_t +#endif // __cplusplus + { + ThereAgain, + SomethingElse, +}; +#ifndef __cplusplus +typedef uint8_t I_Tag; +#endif // __cplusplus + +typedef struct { + uint8_t x; + int16_t y; +} ThereAgain_Body; + +typedef struct { + I_Tag tag; + union { + ThereAgain_Body there_again; + }; +} I; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(A a, B b, C c, D d, F f, H h); +void root(A a, B b, C c, D d, F f, H h, I i); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/derive_ostream.cpp b/tests/expectations/derive_ostream.cpp index 6f2923e..4831cad 100644 --- a/tests/expectations/derive_ostream.cpp +++ b/tests/expectations/derive_ostream.cpp @@ -155,8 +155,30 @@ struct H { }; }; +struct I { + enum class Tag : uint8_t { + ThereAgain, + SomethingElse, + }; + + struct ThereAgain_Body { + uint8_t x; + int16_t y; + + friend std::ostream& operator<<(std::ostream& stream, const ThereAgain_Body& instance) { + return stream << "{ " << "x=" << instance.x << ", " + << "y=" << instance.y << " }"; + } + }; + + Tag tag; + union { + ThereAgain_Body there_again; + }; +}; + extern "C" { -void root(A a, B b, C c, D d, F f, H h); +void root(A a, B b, C c, D d, F f, H h, I i); } // extern "C" diff --git a/tests/expectations/tag/derive_ostream.c b/tests/expectations/tag/derive_ostream.c index c8342b6..a81f01a 100644 --- a/tests/expectations/tag/derive_ostream.c +++ b/tests/expectations/tag/derive_ostream.c @@ -72,4 +72,22 @@ struct H { }; }; -void root(struct A a, struct B b, C c, struct D d, union F f, struct H h); +enum I_Tag { + ThereAgain, + SomethingElse, +}; +typedef uint8_t I_Tag; + +struct ThereAgain_Body { + uint8_t x; + int16_t y; +}; + +struct I { + I_Tag tag; + union { + struct ThereAgain_Body there_again; + }; +}; + +void root(struct A a, struct B b, C c, struct D d, union F f, struct H h, struct I i); diff --git a/tests/expectations/tag/derive_ostream.compat.c b/tests/expectations/tag/derive_ostream.compat.c index c080f7f..7bb4b64 100644 --- a/tests/expectations/tag/derive_ostream.compat.c +++ b/tests/expectations/tag/derive_ostream.compat.c @@ -90,11 +90,35 @@ struct H { }; }; +enum I_Tag +#ifdef __cplusplus + : uint8_t +#endif // __cplusplus + { + ThereAgain, + SomethingElse, +}; +#ifndef __cplusplus +typedef uint8_t I_Tag; +#endif // __cplusplus + +struct ThereAgain_Body { + uint8_t x; + int16_t y; +}; + +struct I { + I_Tag tag; + union { + struct ThereAgain_Body there_again; + }; +}; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(struct A a, struct B b, C c, struct D d, union F f, struct H h); +void root(struct A a, struct B b, C c, struct D d, union F f, struct H h, struct I i); #ifdef __cplusplus } // extern "C" diff --git a/tests/rust/derive_ostream.rs b/tests/rust/derive_ostream.rs index 64e170f..e7e33fa 100644 --- a/tests/rust/derive_ostream.rs +++ b/tests/rust/derive_ostream.rs @@ -1,22 +1,22 @@ /// cbindgen:derive-ostream #[repr(C)] -struct A(i32); +pub struct A(i32); /// cbindgen:field-names=[x, y] /// cbindgen:derive-ostream #[repr(C)] -struct B(i32, f32); +pub struct B(i32, f32); /// cbindgen:derive-ostream #[repr(u32)] -enum C { +pub enum C { X = 2, Y, } /// cbindgen:derive-ostream #[repr(C)] -struct D { +pub struct D { List: u8, Of: usize, Things: B, @@ -24,7 +24,7 @@ struct D { /// cbindgen:derive-ostream #[repr(u8)] -enum F { +pub enum F { Foo(i16), Bar { x: u8, y: i16 }, Baz @@ -32,12 +32,20 @@ enum F { /// cbindgen:derive-ostream #[repr(C, u8)] -enum H { +pub enum H { Hello(i16), There { x: u8, y: i16 }, Everyone } +/// cbindgen:derive-ostream=false +#[repr(C, u8)] +pub enum I { + /// cbindgen:derive-ostream=true + ThereAgain { x: u8, y: i16 }, + SomethingElse +} + #[no_mangle] pub extern "C" fn root( a: A, @@ -46,5 +54,6 @@ pub extern "C" fn root( d: D, f: F, h: H, + i: I, ) { }