Skip to content

Commit

Permalink
bindings: Peel through typedefs for struct constant generation.
Browse files Browse the repository at this point in the history
This allows the workaround in #767 to work.
  • Loading branch information
emilio committed Jun 9, 2022
1 parent 4b30c56 commit b4bf8c6
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
36 changes: 33 additions & 3 deletions src/bindgen/bindings.rs
Expand Up @@ -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::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs;
Expand All @@ -12,7 +13,7 @@ use std::rc::Rc;

use crate::bindgen::config::{Config, Language};
use crate::bindgen::ir::{
Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct,
Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, Typedef,
};
use crate::bindgen::writer::{Source, SourceWriter};

Expand All @@ -22,6 +23,7 @@ pub struct Bindings {
/// The map from path to struct, used to lookup whether a given type is a
/// transparent struct. This is needed to generate code for constants.
struct_map: ItemMap<Struct>,
typedef_map: ItemMap<Typedef>,
struct_fileds_memo: RefCell<HashMap<BindgenPath, Rc<Vec<String>>>>,
globals: Vec<Static>,
constants: Vec<Constant>,
Expand All @@ -42,6 +44,7 @@ impl Bindings {
pub(crate) fn new(
config: Config,
struct_map: ItemMap<Struct>,
typedef_map: ItemMap<Typedef>,
constants: Vec<Constant>,
globals: Vec<Static>,
items: Vec<ItemContainer>,
Expand All @@ -51,6 +54,7 @@ impl Bindings {
Bindings {
config,
struct_map,
typedef_map,
struct_fileds_memo: Default::default(),
globals,
constants,
Expand All @@ -67,9 +71,30 @@ impl Bindings {
any
}

/// Peels through typedefs to allow resolving structs.
fn resolved_struct_path<'a>(&self, path: &'a BindgenPath) -> Cow<'a, BindgenPath> {
use crate::bindgen::ir::Type;

let mut resolved_path = Cow::Borrowed(path);
loop {
let mut found = None;
self.typedef_map.for_items(&resolved_path, |item| {
if let Type::Path(ref p) = item.aliased {
found = Some(p.path().clone());
}
});
resolved_path = match found {
Some(p) => Cow::Owned(p),
None => break,
}
}
resolved_path
}

pub fn struct_exists(&self, path: &BindgenPath) -> bool {
let mut any = false;
self.struct_map.for_items(path, |_| any = true);
self.struct_map
.for_items(&self.resolved_struct_path(path), |_| any = true);
any
}

Expand All @@ -79,8 +104,10 @@ impl Bindings {
return memo.clone();
}

let resolved_path = self.resolved_struct_path(path);

let mut fields = Vec::<String>::new();
self.struct_map.for_items(path, |st| {
self.struct_map.for_items(&resolved_path, |st| {
let mut pos: usize = 0;
for field in &st.fields {
if let Some(found_pos) = fields.iter().position(|v| *v == field.name) {
Expand All @@ -94,6 +121,9 @@ impl Bindings {

let fields = Rc::new(fields);
memos.insert(path.clone(), fields.clone());
if let Cow::Owned(p) = resolved_path {
memos.insert(p, fields.clone());
}
fields
}

Expand Down
2 changes: 2 additions & 0 deletions src/bindgen/library.rs
Expand Up @@ -67,6 +67,7 @@ impl Library {
Default::default(),
Default::default(),
Default::default(),
Default::default(),
true,
));
}
Expand Down Expand Up @@ -147,6 +148,7 @@ impl Library {
Ok(Bindings::new(
self.config,
self.structs,
self.typedefs,
constants,
globals,
items,
Expand Down

0 comments on commit b4bf8c6

Please sign in to comment.