summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c102c47d..b90faba6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,6 +86,7 @@ use std::{env, iter};
// Some convenient typedefs for a fast hash map and hash set.
type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
type HashSet<K> = ::rustc_hash::FxHashSet<K>;
+use quote::ToTokens;
pub(crate) use std::collections::hash_map::Entry;
/// Default prefix for the anon fields.
@@ -587,6 +588,10 @@ impl Builder {
output_vector.push("--vtable-generation".into());
}
+ if self.options.sort_semantically {
+ output_vector.push("--sort-semantically".into());
+ }
+
// Add clang arguments
output_vector.push("--".into());
@@ -1476,6 +1481,14 @@ impl Builder {
self
}
+ /// If true, enables the sorting of the output in a predefined manner
+ ///
+ /// TODO: Perhaps move the sorting order out into a config
+ pub fn sort_semantically(mut self, doit: bool) -> Self {
+ self.options.sort_semantically = doit;
+ self
+ }
+
/// Generate the Rust bindings using the options built up thus far.
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
// Add any extra arguments from the environment to the clang command line.
@@ -2005,6 +2018,9 @@ struct BindgenOptions {
/// Emit vtable functions.
vtable_generation: bool,
+
+ /// Sort the code generation
+ sort_semantically: bool,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2153,6 +2169,7 @@ impl Default for BindgenOptions {
c_naming: false,
force_explicit_padding: false,
vtable_generation: false,
+ sort_semantically: false,
}
}
}
@@ -2438,6 +2455,60 @@ impl Bindings {
let (items, options, warnings) = codegen::codegen(context);
+ if options.sort_semantically {
+ let module_wrapped_tokens =
+ quote!(mod wrapper_for_sorting_hack { #( #items )* });
+
+ // This semantically sorting business is a hack, for now. This means that we are
+ // re-parsing already generated code using `syn` (as opposed to `quote`) because
+ // `syn` provides us more control over the elements.
+ // One caveat is that some of the items coming from `quote`d output might have
+ // multiple items within them. Hence, we have to wrap the incoming in a `mod`.
+ // The two `unwrap`s here are deliberate because
+ // The first one won't panic because we build the `mod` and know it is there
+ // The second one won't panic because we know original output has something in
+ // it already.
+ let mut syn_parsed_items =
+ syn::parse2::<syn::ItemMod>(module_wrapped_tokens)
+ .unwrap()
+ .content
+ .unwrap()
+ .1;
+
+ syn_parsed_items.sort_by_key(|item| match item {
+ syn::Item::Type(_) => 0,
+ syn::Item::Struct(_) => 1,
+ syn::Item::Const(_) => 2,
+ syn::Item::Fn(_) => 3,
+ syn::Item::Enum(_) => 4,
+ syn::Item::Union(_) => 5,
+ syn::Item::Static(_) => 6,
+ syn::Item::Trait(_) => 7,
+ syn::Item::TraitAlias(_) => 8,
+ syn::Item::Impl(_) => 9,
+ syn::Item::Mod(_) => 10,
+ syn::Item::Use(_) => 11,
+ syn::Item::Verbatim(_) => 12,
+ syn::Item::ExternCrate(_) => 13,
+ syn::Item::ForeignMod(_) => 14,
+ syn::Item::Macro(_) => 15,
+ syn::Item::Macro2(_) => 16,
+ _ => 18,
+ });
+
+ let synful_items = syn_parsed_items
+ .into_iter()
+ .map(|item| item.into_token_stream());
+
+ return Ok(Bindings {
+ options,
+ warnings,
+ module: quote! {
+ #( #synful_items )*
+ },
+ });
+ }
+
Ok(Bindings {
options,
warnings,