Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/bindgen/ir/documentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ impl Documentation {
Documentation { doc_comment: doc }
}

pub fn simple(line: &str) -> Self {
Documentation {
doc_comment: vec![line.to_owned()],
}
}

pub fn none() -> Self {
Documentation {
doc_comment: Vec::new(),
Expand Down
20 changes: 14 additions & 6 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,11 @@ impl Enum {
}
}

pub fn load(item: &syn::ItemEnum, mod_cfg: Option<&Cfg>) -> Result<Enum, String> {
pub fn load(
item: &syn::ItemEnum,
mod_cfg: Option<&Cfg>,
config: &Config,
) -> Result<Enum, String> {
let repr = Repr::load(&item.attrs)?;
if repr.style == ReprStyle::Rust && repr.ty.is_none() {
return Err("Enum is not marked with a valid #[repr(prim)] or #[repr(C)].".to_owned());
Expand Down Expand Up @@ -289,6 +293,15 @@ impl Enum {
}
}

if config.enumeration.add_sentinel(&annotations) {
variants.push(EnumVariant::new(
"Sentinel".to_owned(),
None,
None,
Documentation::simple(" Must be last for serialization purposes"),
));
}

let tag = if is_tagged {
Some("Tag".to_string())
} else {
Expand Down Expand Up @@ -596,11 +609,6 @@ impl Source for Enum {
}
variant.write(config, out);
}
if config.enumeration.add_sentinel(&self.annotations) {
out.new_line();
out.new_line();
out.write("Sentinel /* this must be last for serialization purposes. */");
}

if config.language == Language::C && size.is_none() && config.style.generate_typedef() {
out.close_brace(false);
Expand Down
12 changes: 9 additions & 3 deletions src/bindgen/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ impl Parse {
self.load_syn_union(config, crate_name, mod_cfg, item);
}
syn::Item::Enum(ref item) => {
self.load_syn_enum(crate_name, mod_cfg, item);
self.load_syn_enum(config, crate_name, mod_cfg, item);
}
syn::Item::Type(ref item) => {
self.load_syn_ty(crate_name, mod_cfg, item);
Expand Down Expand Up @@ -860,7 +860,13 @@ impl Parse {
}

/// Loads a `enum` declaration
fn load_syn_enum(&mut self, crate_name: &str, mod_cfg: Option<&Cfg>, item: &syn::ItemEnum) {
fn load_syn_enum(
&mut self,
config: &Config,
crate_name: &str,
mod_cfg: Option<&Cfg>,
item: &syn::ItemEnum,
) {
if item.generics.lifetimes().count() > 0 {
info!(
"Skip {}::{} - (has generics or lifetimes or where bounds).",
Expand All @@ -869,7 +875,7 @@ impl Parse {
return;
}

match Enum::load(item, mod_cfg) {
match Enum::load(item, mod_cfg, config) {
Ok(en) => {
info!("Take {}::{}.", crate_name, &item.ident);
self.enums.try_insert(en);
Expand Down
55 changes: 55 additions & 0 deletions tests/expectations/both/sentinel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum A {
A_A1,
A_A2,
A_A3,
/**
* Must be last for serialization purposes
*/
A_Sentinel,
};
typedef uint8_t A;

enum B {
B_B1,
B_B2,
B_B3,
/**
* Must be last for serialization purposes
*/
B_Sentinel,
};
typedef uint8_t B;

enum C_Tag {
C_C1,
C_C2,
C_C3,
/**
* Must be last for serialization purposes
*/
C_Sentinel,
};
typedef uint8_t C_Tag;

typedef struct C_C1_Body {
C_Tag tag;
uint32_t a;
} C_C1_Body;

typedef struct C_C2_Body {
C_Tag tag;
uint32_t b;
} C_C2_Body;

typedef union C {
C_Tag tag;
C_C1_Body c1;
C_C2_Body c2;
} C;

void root(A a, B b, C c);
81 changes: 81 additions & 0 deletions tests/expectations/both/sentinel.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum A
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
A_A1,
A_A2,
A_A3,
/**
* Must be last for serialization purposes
*/
A_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t A;
#endif // __cplusplus

enum B
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
B_B1,
B_B2,
B_B3,
/**
* Must be last for serialization purposes
*/
B_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t B;
#endif // __cplusplus

enum C_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
C_C1,
C_C2,
C_C3,
/**
* Must be last for serialization purposes
*/
C_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t C_Tag;
#endif // __cplusplus

typedef struct C_C1_Body {
C_Tag tag;
uint32_t a;
} C_C1_Body;

typedef struct C_C2_Body {
C_Tag tag;
uint32_t b;
} C_C2_Body;

typedef union C {
C_Tag tag;
C_C1_Body c1;
C_C2_Body c2;
} C;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void root(A a, B b, C c);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
55 changes: 55 additions & 0 deletions tests/expectations/sentinel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum A {
A_A1,
A_A2,
A_A3,
/**
* Must be last for serialization purposes
*/
A_Sentinel,
};
typedef uint8_t A;

enum B {
B_B1,
B_B2,
B_B3,
/**
* Must be last for serialization purposes
*/
B_Sentinel,
};
typedef uint8_t B;

enum C_Tag {
C_C1,
C_C2,
C_C3,
/**
* Must be last for serialization purposes
*/
C_Sentinel,
};
typedef uint8_t C_Tag;

typedef struct {
C_Tag tag;
uint32_t a;
} C_C1_Body;

typedef struct {
C_Tag tag;
uint32_t b;
} C_C2_Body;

typedef union {
C_Tag tag;
C_C1_Body c1;
C_C2_Body c2;
} C;

void root(A a, B b, C c);
81 changes: 81 additions & 0 deletions tests/expectations/sentinel.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum A
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
A_A1,
A_A2,
A_A3,
/**
* Must be last for serialization purposes
*/
A_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t A;
#endif // __cplusplus

enum B
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
B_B1,
B_B2,
B_B3,
/**
* Must be last for serialization purposes
*/
B_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t B;
#endif // __cplusplus

enum C_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
C_C1,
C_C2,
C_C3,
/**
* Must be last for serialization purposes
*/
C_Sentinel,
};
#ifndef __cplusplus
typedef uint8_t C_Tag;
#endif // __cplusplus

typedef struct {
C_Tag tag;
uint32_t a;
} C_C1_Body;

typedef struct {
C_Tag tag;
uint32_t b;
} C_C2_Body;

typedef union {
C_Tag tag;
C_C1_Body c1;
C_C2_Body c2;
} C;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void root(A a, B b, C c);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
Loading