diff --git a/Cargo.lock b/Cargo.lock index 142112a213..e3d06d9722 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -550,6 +550,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "shlex" version = "1.3.0" @@ -620,6 +640,7 @@ dependencies = [ "block", "libloading", "objc", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index cd5e4e6223..9494919f67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ quickcheck = "1.0" quote = { version = "1", default-features = false } regex = { version = "1.5.3", default-features = false } rustc-hash = "2.1.0" +serde = { version = "1", features = ["derive"] } shlex = "1" similar = "2.2.1" syn = "2.0" diff --git a/bindgen-tests/tests/expectations/Cargo.toml b/bindgen-tests/tests/expectations/Cargo.toml index 975fd16678..78c91a9c95 100644 --- a/bindgen-tests/tests/expectations/Cargo.toml +++ b/bindgen-tests/tests/expectations/Cargo.toml @@ -15,6 +15,7 @@ edition.workspace = true block.workspace = true libloading.workspace = true objc.workspace = true +serde.workspace = true # Both of these sections need to be copied here from the workspace because # Cargo currently does not allow overriding workspace settings in a member diff --git a/bindgen-tests/tests/expectations/tests/derive-and-attribute-order.rs b/bindgen-tests/tests/expectations/tests/derive-and-attribute-order.rs new file mode 100644 index 0000000000..ecb81f3f93 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/derive-and-attribute-order.rs @@ -0,0 +1,5 @@ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +# [repr (C)] # [derive (Debug , Default , Copy , Clone , serde :: Serialize)] # [serde (rename_all = "UPPERCASE")] pub struct color { pub red : :: std :: os :: raw :: c_int , pub green : :: std :: os :: raw :: c_int , pub blue : :: std :: os :: raw :: c_int , } \ No newline at end of file diff --git a/bindgen-tests/tests/headers/derive-and-attribute-order.h b/bindgen-tests/tests/headers/derive-and-attribute-order.h new file mode 100644 index 0000000000..f404b3abd1 --- /dev/null +++ b/bindgen-tests/tests/headers/derive-and-attribute-order.h @@ -0,0 +1,8 @@ +// bindgen-flags: --no-layout-tests +// bindgen-parse-callbacks: derive-uppercase-serialize=color +// bindgen-skip-formatting +typedef struct { + int red; + int green; + int blue; +} color; diff --git a/bindgen-tests/tests/parse_callbacks/mod.rs b/bindgen-tests/tests/parse_callbacks/mod.rs index 7aca0fd1a1..b3d3d1b7b3 100644 --- a/bindgen-tests/tests/parse_callbacks/mod.rs +++ b/bindgen-tests/tests/parse_callbacks/mod.rs @@ -146,6 +146,27 @@ impl ParseCallbacks for WrapAsVariadicFn { } } +#[derive(Debug)] +struct DeriveTransparentSerialize(String); + +impl ParseCallbacks for DeriveTransparentSerialize { + fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec { + if info.name == &self.0 { + vec!["serde::Serialize".to_owned()] + } else { + vec![] + } + } + + fn add_attributes(&self, info: &AttributeInfo<'_>) -> Vec { + if info.name == &self.0 { + vec!["#[serde(rename_all = \"UPPERCASE\")]".to_owned()] + } else { + vec![] + } + } +} + pub fn lookup(cb: &str) -> Box { match cb { "enum-variant-rename" => Box::new(EnumVariantRename), @@ -155,7 +176,11 @@ pub fn lookup(cb: &str) -> Box { "wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn), "type-visibility" => Box::new(TypeVisibility), call_back => { - if let Some(prefix) = + if let Some(name) = + call_back.strip_prefix("derive-uppercase-serialize=") + { + Box::new(DeriveTransparentSerialize(name.to_owned())) + } else if let Some(prefix) = call_back.strip_prefix("remove-function-prefix-") { let lnopc = RemovePrefixParseCallback::new(prefix); diff --git a/bindgen-tests/tests/tests.rs b/bindgen-tests/tests/tests.rs index 0b3ebe1533..40486eda40 100644 --- a/bindgen-tests/tests/tests.rs +++ b/bindgen-tests/tests/tests.rs @@ -187,17 +187,23 @@ fn compare_generated_header( looked_at, ), }; - + let do_formatting = builder.do_formatting; let (builder, roundtrip_builder) = builder.into_builder(check_roundtrip)?; // We skip the generate() error here so we get a full diff below let actual = match builder.generate() { - Ok(bindings) => format_code(bindings.to_string()).map_err(|err| { - Error::new( - ErrorKind::Other, - format!("Cannot parse the generated bindings: {err}"), - ) - })?, + Ok(bindings) => { + if do_formatting { + format_code(bindings.to_string()).map_err(|err| { + Error::new( + ErrorKind::Other, + format!("Cannot parse the generated bindings: {err}"), + ) + })? + } else { + bindings.to_string() + } + } Err(_) => "/* error generating bindings */\n".into(), }; @@ -237,6 +243,7 @@ fn builder() -> Builder { struct BuilderState { builder: Builder, parse_callbacks: Option, + do_formatting: bool, } impl BuilderState { @@ -255,6 +262,7 @@ impl BuilderState { Some(BuilderState { builder, parse_callbacks: self.parse_callbacks, + do_formatting: self.do_formatting, }) } else { None @@ -273,6 +281,7 @@ fn create_bindgen_builder(header: &Path) -> Result { // Scoop up bindgen-flags from test header let mut flags = Vec::with_capacity(2); let mut parse_callbacks = None; + let mut do_formatting = true; for line in reader.lines() { let line = line?; @@ -298,6 +307,8 @@ fn create_bindgen_builder(header: &Path) -> Result { let parse_cb = line.split("bindgen-parse-callbacks: ").last().unwrap(); parse_callbacks = Some(parse_cb.to_owned()); + } else if line.contains("bindgen-skip-formatting") { + do_formatting = false; } } @@ -345,6 +356,7 @@ fn create_bindgen_builder(header: &Path) -> Result { Ok(BuilderState { builder, parse_callbacks, + do_formatting, }) }