Add support for out-of-line bitfields declarations
This commit is contained in:
committed by
Emilio Cobos Álvarez
parent
35f2e44ef2
commit
9b4a14958e
+106
-36
@@ -15,7 +15,7 @@ use syn::parse::{Parse, ParseStream, Parser, Result as ParseResult};
|
||||
// )+
|
||||
// }
|
||||
#[derive(Debug)]
|
||||
pub struct Bitflags {
|
||||
pub struct BitflagsStruct {
|
||||
attrs: Vec<syn::Attribute>,
|
||||
vis: syn::Visibility,
|
||||
#[allow(dead_code)]
|
||||
@@ -27,46 +27,91 @@ pub struct Bitflags {
|
||||
flags: Flags,
|
||||
}
|
||||
|
||||
// impl $BitFlags:ident: $T:ty {
|
||||
// $(
|
||||
// $(#[$inner:ident $($args:tt)*])*
|
||||
// const $Flag:ident = $value:expr;
|
||||
// )+
|
||||
// }
|
||||
#[derive(Debug)]
|
||||
pub struct BitflagsImpl {
|
||||
#[allow(dead_code)]
|
||||
impl_token: Token![impl],
|
||||
name: syn::Ident,
|
||||
#[allow(dead_code)]
|
||||
colon_token: Token![:],
|
||||
repr: syn::Type,
|
||||
flags: Flags,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Bitflags {
|
||||
Struct(BitflagsStruct),
|
||||
Impl(BitflagsImpl),
|
||||
}
|
||||
|
||||
impl Bitflags {
|
||||
pub fn expand(&self) -> (syn::ItemStruct, syn::ItemImpl) {
|
||||
let Bitflags {
|
||||
ref attrs,
|
||||
ref vis,
|
||||
ref name,
|
||||
ref repr,
|
||||
ref flags,
|
||||
..
|
||||
} = *self;
|
||||
pub fn expand(&self) -> (Option<syn::ItemStruct>, syn::ItemImpl) {
|
||||
match self {
|
||||
Bitflags::Struct(BitflagsStruct {
|
||||
attrs,
|
||||
vis,
|
||||
name,
|
||||
repr,
|
||||
flags,
|
||||
..
|
||||
}) => {
|
||||
let struct_ = parse_quote! {
|
||||
#(#attrs)*
|
||||
#vis struct #name {
|
||||
bits: #repr,
|
||||
}
|
||||
};
|
||||
|
||||
let struct_ = parse_quote! {
|
||||
/// cbindgen:internal-derive-bitflags=true
|
||||
#(#attrs)*
|
||||
#vis struct #name {
|
||||
bits: #repr,
|
||||
let consts = flags.expand(name, repr, false);
|
||||
let impl_ = parse_quote! {
|
||||
impl #name {
|
||||
#consts
|
||||
}
|
||||
};
|
||||
|
||||
(Some(struct_), impl_)
|
||||
}
|
||||
};
|
||||
|
||||
let consts = flags.expand(name, repr);
|
||||
let impl_ = parse_quote! {
|
||||
impl #name {
|
||||
#consts
|
||||
Bitflags::Impl(BitflagsImpl {
|
||||
name, repr, flags, ..
|
||||
}) => {
|
||||
let consts = flags.expand(name, repr, true);
|
||||
let impl_: syn::ItemImpl = parse_quote! {
|
||||
impl #name {
|
||||
#consts
|
||||
}
|
||||
};
|
||||
(None, impl_)
|
||||
}
|
||||
};
|
||||
|
||||
(struct_, impl_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Bitflags {
|
||||
fn parse(input: ParseStream) -> ParseResult<Self> {
|
||||
Ok(Self {
|
||||
attrs: input.call(syn::Attribute::parse_outer)?,
|
||||
vis: input.parse()?,
|
||||
struct_token: input.parse()?,
|
||||
name: input.parse()?,
|
||||
colon_token: input.parse()?,
|
||||
repr: input.parse()?,
|
||||
flags: input.parse()?,
|
||||
Ok(if input.peek(Token![impl]) {
|
||||
Self::Impl(BitflagsImpl {
|
||||
impl_token: input.parse()?,
|
||||
name: input.parse()?,
|
||||
colon_token: input.parse()?,
|
||||
repr: input.parse()?,
|
||||
flags: input.parse()?,
|
||||
})
|
||||
} else {
|
||||
Self::Struct(BitflagsStruct {
|
||||
attrs: input.call(syn::Attribute::parse_outer)?,
|
||||
vis: input.parse()?,
|
||||
struct_token: input.parse()?,
|
||||
name: input.parse()?,
|
||||
colon_token: input.parse()?,
|
||||
repr: input.parse()?,
|
||||
flags: input.parse()?,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -89,6 +134,7 @@ struct Flag {
|
||||
struct FlagValueFold<'a> {
|
||||
struct_name: &'a syn::Ident,
|
||||
flag_names: &'a HashSet<String>,
|
||||
out_of_line: bool,
|
||||
}
|
||||
|
||||
impl<'a> FlagValueFold<'a> {
|
||||
@@ -114,6 +160,19 @@ impl<'a> Fold for FlagValueFold<'a> {
|
||||
// as far as our bindings generation is concerned, `bits` is available as a field,
|
||||
// so by replacing `StructName::FLAG.bits()` with `StructName::FLAG.bits`, we make
|
||||
// e.g. `Flags::AB` available in the generated bindings.
|
||||
// For out-of-line definitions of the struct(*), where the struct is defined as a
|
||||
// newtype, we replace it with `StructName::FLAGS.0`.
|
||||
// * definitions like:
|
||||
// ```
|
||||
// struct Flags(u8);
|
||||
// bitflags! {
|
||||
// impl Flags: u8 {
|
||||
// const A = 1;
|
||||
// const B = 1 << 1;
|
||||
// const AB = Flags::A.bits() | Flags::B.bits();
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
match node {
|
||||
syn::Expr::MethodCall(syn::ExprMethodCall {
|
||||
attrs,
|
||||
@@ -136,7 +195,11 @@ impl<'a> Fold for FlagValueFold<'a> {
|
||||
attrs,
|
||||
base: receiver,
|
||||
dot_token,
|
||||
member: syn::Member::Named(method),
|
||||
member: if self.out_of_line {
|
||||
syn::Member::Unnamed(parse_quote! {0})
|
||||
} else {
|
||||
syn::Member::Named(method)
|
||||
},
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
@@ -151,6 +214,7 @@ impl Flag {
|
||||
struct_name: &syn::Ident,
|
||||
repr: &syn::Type,
|
||||
flag_names: &HashSet<String>,
|
||||
out_of_line: bool,
|
||||
) -> TokenStream {
|
||||
let Flag {
|
||||
ref attrs,
|
||||
@@ -161,11 +225,17 @@ impl Flag {
|
||||
let folded_value = FlagValueFold {
|
||||
struct_name,
|
||||
flag_names,
|
||||
out_of_line,
|
||||
}
|
||||
.fold_expr(value.clone());
|
||||
let value = if out_of_line {
|
||||
quote! { ((#folded_value) as #repr) }
|
||||
} else {
|
||||
quote! { { bits: (#folded_value) as #repr } }
|
||||
};
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
pub const #name : #struct_name = #struct_name { bits: (#folded_value) as #repr };
|
||||
pub const #name : #struct_name = #struct_name #value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,7 +269,7 @@ impl Parse for Flags {
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
fn expand(&self, struct_name: &syn::Ident, repr: &syn::Type) -> TokenStream {
|
||||
fn expand(&self, struct_name: &syn::Ident, repr: &syn::Type, out_of_line: bool) -> TokenStream {
|
||||
let mut ts = quote! {};
|
||||
let flag_names = self
|
||||
.0
|
||||
@@ -207,7 +277,7 @@ impl Flags {
|
||||
.map(|flag| flag.name.to_string())
|
||||
.collect::<HashSet<_>>();
|
||||
for flag in &self.0 {
|
||||
ts.extend(flag.expand(struct_name, repr, &flag_names));
|
||||
ts.extend(flag.expand(struct_name, repr, &flag_names, out_of_line));
|
||||
}
|
||||
ts
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ impl Struct {
|
||||
other: &str,
|
||||
out: &mut SourceWriter<F>,
|
||||
) {
|
||||
let bits = &self.fields[0].name;
|
||||
out.new_line();
|
||||
write!(
|
||||
out,
|
||||
@@ -223,10 +224,8 @@ impl Struct {
|
||||
out.open_brace();
|
||||
write!(
|
||||
out,
|
||||
"return {} {{ static_cast<decltype(bits)>(this->bits {} {}.bits) }};",
|
||||
self.export_name(),
|
||||
operator,
|
||||
other
|
||||
"return {} {{ static_cast<decltype({bits})>(this->{bits} {operator} {other}.{bits}) }};",
|
||||
self.export_name()
|
||||
);
|
||||
out.close_brace(false);
|
||||
|
||||
@@ -534,6 +533,8 @@ impl Source for Struct {
|
||||
.bool("internal-derive-bitflags")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
assert_eq!(self.fields.len(), 1);
|
||||
let bits = &self.fields[0].name;
|
||||
if !wrote_start_newline {
|
||||
wrote_start_newline = true;
|
||||
out.new_line();
|
||||
@@ -547,7 +548,7 @@ impl Source for Struct {
|
||||
out.new_line();
|
||||
write!(out, "{}explicit operator bool() const", constexpr_prefix);
|
||||
out.open_brace();
|
||||
write!(out, "return !!bits;");
|
||||
write!(out, "return !!{bits};");
|
||||
out.close_brace(false);
|
||||
|
||||
out.new_line();
|
||||
@@ -560,7 +561,7 @@ impl Source for Struct {
|
||||
out.open_brace();
|
||||
write!(
|
||||
out,
|
||||
"return {} {{ static_cast<decltype(bits)>(~bits) }};",
|
||||
"return {} {{ static_cast<decltype({bits})>(~{bits}) }};",
|
||||
self.export_name()
|
||||
);
|
||||
out.close_brace(false);
|
||||
|
||||
+17
-9
@@ -15,8 +15,8 @@ use crate::bindgen::cargo::{Cargo, PackageRef};
|
||||
use crate::bindgen::config::{Config, ParseConfig};
|
||||
use crate::bindgen::error::Error;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams,
|
||||
ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
|
||||
AnnotationSet, AnnotationValue, Cfg, Constant, Documentation, Enum, Function, GenericParam,
|
||||
GenericParams, ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
|
||||
};
|
||||
use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemHelpers};
|
||||
|
||||
@@ -547,7 +547,7 @@ impl Parse {
|
||||
}
|
||||
}
|
||||
syn::Item::Macro(ref item) => {
|
||||
self.load_builtin_macro(config, crate_name, mod_cfg, item)
|
||||
self.load_builtin_macro(config, crate_name, mod_cfg, item);
|
||||
}
|
||||
syn::Item::Mod(ref item) => {
|
||||
nested_modules.push(item);
|
||||
@@ -986,7 +986,7 @@ impl Parse {
|
||||
}
|
||||
|
||||
let bitflags = match bitflags::parse(item.mac.tokens.clone()) {
|
||||
Ok(b) => b,
|
||||
Ok(bf) => bf,
|
||||
Err(e) => {
|
||||
warn!("Failed to parse bitflags invocation: {:?}", e);
|
||||
return;
|
||||
@@ -994,10 +994,18 @@ impl Parse {
|
||||
};
|
||||
|
||||
let (struct_, impl_) = bitflags.expand();
|
||||
self.load_syn_struct(config, crate_name, mod_cfg, &struct_);
|
||||
// We know that the expansion will only reference `struct_`, so it's
|
||||
// fine to just do it here instead of deferring it like we do with the
|
||||
// other calls to this function.
|
||||
self.load_syn_assoc_consts_from_impl(crate_name, mod_cfg, &impl_);
|
||||
if let Some(struct_) = struct_ {
|
||||
self.load_syn_struct(config, crate_name, mod_cfg, &struct_);
|
||||
}
|
||||
if let syn::Type::Path(ref path) = *impl_.self_ty {
|
||||
if let Some(type_name) = path.path.get_ident() {
|
||||
self.structs
|
||||
.for_items_mut(&Path::new(type_name.unraw().to_string()), |item| {
|
||||
item.annotations
|
||||
.add_default("internal-derive-bitflags", AnnotationValue::Bool(true));
|
||||
});
|
||||
}
|
||||
}
|
||||
self.load_syn_assoc_consts_from_impl(crate_name, mod_cfg, &impl_)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,14 @@ typedef struct {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags);
|
||||
typedef struct {
|
||||
uint32_t _0;
|
||||
} OutOfLine;
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
void root(AlignFlags flags,
|
||||
DebugFlags bigger_flags,
|
||||
LargeFlags largest_flags,
|
||||
OutOfLine out_of_line);
|
||||
|
||||
@@ -52,11 +52,21 @@ typedef struct {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
typedef struct {
|
||||
uint32_t _0;
|
||||
} OutOfLine;
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags);
|
||||
void root(AlignFlags flags,
|
||||
DebugFlags bigger_flags,
|
||||
LargeFlags largest_flags,
|
||||
OutOfLine out_of_line);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -121,8 +121,46 @@ struct LargeFlags {
|
||||
constexpr static const LargeFlags LargeFlags_LARGE_SHIFT = LargeFlags{ /* .bits = */ (uint64_t)(1ull << 44) };
|
||||
constexpr static const LargeFlags LargeFlags_INVERTED = LargeFlags{ /* .bits = */ (uint64_t)~(LargeFlags_LARGE_SHIFT).bits };
|
||||
|
||||
struct OutOfLine {
|
||||
uint32_t _0;
|
||||
|
||||
constexpr explicit operator bool() const {
|
||||
return !!_0;
|
||||
}
|
||||
constexpr OutOfLine operator~() const {
|
||||
return OutOfLine { static_cast<decltype(_0)>(~_0) };
|
||||
}
|
||||
constexpr OutOfLine operator|(const OutOfLine& other) const {
|
||||
return OutOfLine { static_cast<decltype(_0)>(this->_0 | other._0) };
|
||||
}
|
||||
OutOfLine& operator|=(const OutOfLine& other) {
|
||||
*this = (*this | other);
|
||||
return *this;
|
||||
}
|
||||
constexpr OutOfLine operator&(const OutOfLine& other) const {
|
||||
return OutOfLine { static_cast<decltype(_0)>(this->_0 & other._0) };
|
||||
}
|
||||
OutOfLine& operator&=(const OutOfLine& other) {
|
||||
*this = (*this & other);
|
||||
return *this;
|
||||
}
|
||||
constexpr OutOfLine operator^(const OutOfLine& other) const {
|
||||
return OutOfLine { static_cast<decltype(_0)>(this->_0 ^ other._0) };
|
||||
}
|
||||
OutOfLine& operator^=(const OutOfLine& other) {
|
||||
*this = (*this ^ other);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
constexpr static const OutOfLine OutOfLine_A = OutOfLine{ /* ._0 = */ (uint32_t)1 };
|
||||
constexpr static const OutOfLine OutOfLine_B = OutOfLine{ /* ._0 = */ (uint32_t)2 };
|
||||
constexpr static const OutOfLine OutOfLine_AB = OutOfLine{ /* ._0 = */ (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) };
|
||||
|
||||
extern "C" {
|
||||
|
||||
void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags);
|
||||
void root(AlignFlags flags,
|
||||
DebugFlags bigger_flags,
|
||||
LargeFlags largest_flags,
|
||||
OutOfLine out_of_line);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -36,4 +36,13 @@ cdef extern from *:
|
||||
const LargeFlags LargeFlags_LARGE_SHIFT # = <LargeFlags>{ <uint64_t>(1ull << 44) }
|
||||
const LargeFlags LargeFlags_INVERTED # = <LargeFlags>{ <uint64_t>~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags);
|
||||
ctypedef struct OutOfLine:
|
||||
uint32_t _0;
|
||||
const OutOfLine OutOfLine_A # = <OutOfLine>{ <uint32_t>1 }
|
||||
const OutOfLine OutOfLine_B # = <OutOfLine>{ <uint32_t>2 }
|
||||
const OutOfLine OutOfLine_AB # = <OutOfLine>{ <uint32_t>((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
void root(AlignFlags flags,
|
||||
DebugFlags bigger_flags,
|
||||
LargeFlags largest_flags,
|
||||
OutOfLine out_of_line);
|
||||
|
||||
@@ -52,4 +52,14 @@ typedef struct LargeFlags {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags);
|
||||
typedef struct OutOfLine {
|
||||
uint32_t _0;
|
||||
} OutOfLine;
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
void root(struct AlignFlags flags,
|
||||
struct DebugFlags bigger_flags,
|
||||
struct LargeFlags largest_flags,
|
||||
struct OutOfLine out_of_line);
|
||||
|
||||
@@ -52,11 +52,21 @@ typedef struct LargeFlags {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
typedef struct OutOfLine {
|
||||
uint32_t _0;
|
||||
} OutOfLine;
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags);
|
||||
void root(struct AlignFlags flags,
|
||||
struct DebugFlags bigger_flags,
|
||||
struct LargeFlags largest_flags,
|
||||
struct OutOfLine out_of_line);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -52,4 +52,14 @@ struct LargeFlags {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags);
|
||||
struct OutOfLine {
|
||||
uint32_t _0;
|
||||
};
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
void root(struct AlignFlags flags,
|
||||
struct DebugFlags bigger_flags,
|
||||
struct LargeFlags largest_flags,
|
||||
struct OutOfLine out_of_line);
|
||||
|
||||
@@ -52,11 +52,21 @@ struct LargeFlags {
|
||||
#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) }
|
||||
#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
struct OutOfLine {
|
||||
uint32_t _0;
|
||||
};
|
||||
#define OutOfLine_A (OutOfLine){ ._0 = (uint32_t)1 }
|
||||
#define OutOfLine_B (OutOfLine){ ._0 = (uint32_t)2 }
|
||||
#define OutOfLine_AB (OutOfLine){ ._0 = (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags);
|
||||
void root(struct AlignFlags flags,
|
||||
struct DebugFlags bigger_flags,
|
||||
struct LargeFlags largest_flags,
|
||||
struct OutOfLine out_of_line);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -36,4 +36,13 @@ cdef extern from *:
|
||||
const LargeFlags LargeFlags_LARGE_SHIFT # = <LargeFlags>{ <uint64_t>(1ull << 44) }
|
||||
const LargeFlags LargeFlags_INVERTED # = <LargeFlags>{ <uint64_t>~(LargeFlags_LARGE_SHIFT).bits }
|
||||
|
||||
void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags);
|
||||
cdef struct OutOfLine:
|
||||
uint32_t _0;
|
||||
const OutOfLine OutOfLine_A # = <OutOfLine>{ <uint32_t>1 }
|
||||
const OutOfLine OutOfLine_B # = <OutOfLine>{ <uint32_t>2 }
|
||||
const OutOfLine OutOfLine_AB # = <OutOfLine>{ <uint32_t>((OutOfLine_A)._0 | (OutOfLine_B)._0) }
|
||||
|
||||
void root(AlignFlags flags,
|
||||
DebugFlags bigger_flags,
|
||||
LargeFlags largest_flags,
|
||||
OutOfLine out_of_line);
|
||||
|
||||
+19
-1
@@ -38,6 +38,24 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
// bitflags 2 allows to define types out-of-line for custom derives
|
||||
// #[derive(SomeTrait)]
|
||||
#[repr(C)]
|
||||
pub struct OutOfLine(u32);
|
||||
|
||||
bitflags! {
|
||||
impl OutOfLine: u32 {
|
||||
const A = 1;
|
||||
const B = 2;
|
||||
const AB = Self::A.bits() | Self::B.bits();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn root(flags: AlignFlags, bigger_flags: DebugFlags, largest_flags: LargeFlags) {}
|
||||
pub extern "C" fn root(
|
||||
flags: AlignFlags,
|
||||
bigger_flags: DebugFlags,
|
||||
largest_flags: LargeFlags,
|
||||
out_of_line: OutOfLine,
|
||||
) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user