RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
445
zeroidc/vendor/cbindgen/src/bindgen/bindings.rs
vendored
Normal file
445
zeroidc/vendor/cbindgen/src/bindgen/bindings.rs
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::ir::{
|
||||
Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct,
|
||||
};
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
/// A bindings header that can be written.
|
||||
pub struct Bindings {
|
||||
pub config: Config,
|
||||
/// 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>,
|
||||
struct_fileds_memo: RefCell<HashMap<BindgenPath, Rc<Vec<String>>>>,
|
||||
globals: Vec<Static>,
|
||||
constants: Vec<Constant>,
|
||||
items: Vec<ItemContainer>,
|
||||
functions: Vec<Function>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum NamespaceOperation {
|
||||
Open,
|
||||
Close,
|
||||
}
|
||||
|
||||
impl Bindings {
|
||||
pub(crate) fn new(
|
||||
config: Config,
|
||||
struct_map: ItemMap<Struct>,
|
||||
constants: Vec<Constant>,
|
||||
globals: Vec<Static>,
|
||||
items: Vec<ItemContainer>,
|
||||
functions: Vec<Function>,
|
||||
) -> Bindings {
|
||||
Bindings {
|
||||
config,
|
||||
struct_map,
|
||||
struct_fileds_memo: Default::default(),
|
||||
globals,
|
||||
constants,
|
||||
items,
|
||||
functions,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(emilio): What to do when the configuration doesn't match?
|
||||
pub fn struct_is_transparent(&self, path: &BindgenPath) -> bool {
|
||||
let mut any = false;
|
||||
self.struct_map.for_items(path, |s| any |= s.is_transparent);
|
||||
any
|
||||
}
|
||||
|
||||
pub fn struct_exists(&self, path: &BindgenPath) -> bool {
|
||||
let mut any = false;
|
||||
self.struct_map.for_items(path, |_| any = true);
|
||||
any
|
||||
}
|
||||
|
||||
pub fn struct_field_names(&self, path: &BindgenPath) -> Rc<Vec<String>> {
|
||||
let mut memos = self.struct_fileds_memo.borrow_mut();
|
||||
if let Some(memo) = memos.get(path) {
|
||||
return memo.clone();
|
||||
}
|
||||
|
||||
let mut fields = Vec::<String>::new();
|
||||
self.struct_map.for_items(path, |st| {
|
||||
let mut pos: usize = 0;
|
||||
for field in &st.fields {
|
||||
if let Some(found_pos) = fields.iter().position(|v| *v == field.name) {
|
||||
pos = found_pos + 1;
|
||||
} else {
|
||||
fields.insert(pos, field.name.clone());
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let fields = Rc::new(fields);
|
||||
memos.insert(path.clone(), fields.clone());
|
||||
fields
|
||||
}
|
||||
|
||||
pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
|
||||
// Don't compare files if we've never written this file before
|
||||
if !path.as_ref().is_file() {
|
||||
if let Some(parent) = path::Path::new(path.as_ref()).parent() {
|
||||
fs::create_dir_all(parent).unwrap();
|
||||
}
|
||||
self.write(File::create(path).unwrap());
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut new_file_contents = Vec::new();
|
||||
self.write(&mut new_file_contents);
|
||||
|
||||
let mut old_file_contents = Vec::new();
|
||||
{
|
||||
let mut old_file = File::open(&path).unwrap();
|
||||
old_file.read_to_end(&mut old_file_contents).unwrap();
|
||||
}
|
||||
|
||||
if old_file_contents != new_file_contents {
|
||||
let mut new_file = File::create(&path).unwrap();
|
||||
new_file.write_all(&new_file_contents).unwrap();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
|
||||
if let Some(ref f) = self.config.header {
|
||||
out.new_line_if_not_start();
|
||||
write!(out, "{}", f);
|
||||
out.new_line();
|
||||
}
|
||||
if let Some(f) = self.config.include_guard() {
|
||||
out.new_line_if_not_start();
|
||||
write!(out, "#ifndef {}", f);
|
||||
out.new_line();
|
||||
write!(out, "#define {}", f);
|
||||
out.new_line();
|
||||
}
|
||||
if self.config.pragma_once && self.config.language != Language::Cython {
|
||||
out.new_line_if_not_start();
|
||||
write!(out, "#pragma once");
|
||||
out.new_line();
|
||||
}
|
||||
if self.config.include_version {
|
||||
out.new_line_if_not_start();
|
||||
write!(
|
||||
out,
|
||||
"/* Generated with cbindgen:{} */",
|
||||
crate::bindgen::config::VERSION
|
||||
);
|
||||
out.new_line();
|
||||
}
|
||||
if let Some(ref f) = self.config.autogen_warning {
|
||||
out.new_line_if_not_start();
|
||||
write!(out, "{}", f);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.no_includes
|
||||
&& self.config.sys_includes().is_empty()
|
||||
&& self.config.includes().is_empty()
|
||||
&& (self.config.cython.cimports.is_empty() || self.config.language != Language::Cython)
|
||||
&& self.config.after_includes.is_none()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
out.new_line_if_not_start();
|
||||
|
||||
if !self.config.no_includes {
|
||||
match self.config.language {
|
||||
Language::C => {
|
||||
out.write("#include <stdarg.h>");
|
||||
out.new_line();
|
||||
out.write("#include <stdbool.h>");
|
||||
out.new_line();
|
||||
if self.config.usize_is_size_t {
|
||||
out.write("#include <stddef.h>");
|
||||
out.new_line();
|
||||
}
|
||||
out.write("#include <stdint.h>");
|
||||
out.new_line();
|
||||
out.write("#include <stdlib.h>");
|
||||
out.new_line();
|
||||
}
|
||||
Language::Cxx => {
|
||||
out.write("#include <cstdarg>");
|
||||
out.new_line();
|
||||
if self.config.usize_is_size_t {
|
||||
out.write("#include <cstddef>");
|
||||
out.new_line();
|
||||
}
|
||||
out.write("#include <cstdint>");
|
||||
out.new_line();
|
||||
out.write("#include <cstdlib>");
|
||||
out.new_line();
|
||||
out.write("#include <ostream>");
|
||||
out.new_line();
|
||||
out.write("#include <new>");
|
||||
out.new_line();
|
||||
if self.config.enumeration.cast_assert_name.is_none()
|
||||
&& (self.config.enumeration.derive_mut_casts
|
||||
|| self.config.enumeration.derive_const_casts)
|
||||
{
|
||||
out.write("#include <cassert>");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
Language::Cython => {
|
||||
out.write(
|
||||
"from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t",
|
||||
);
|
||||
out.new_line();
|
||||
out.write(
|
||||
"from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t",
|
||||
);
|
||||
out.new_line();
|
||||
out.write("cdef extern from *");
|
||||
out.open_brace();
|
||||
out.write("ctypedef bint bool");
|
||||
out.new_line();
|
||||
out.write("ctypedef struct va_list");
|
||||
out.new_line();
|
||||
out.close_brace(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for include in self.config.sys_includes() {
|
||||
write!(out, "#include <{}>", include);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
for include in self.config.includes() {
|
||||
write!(out, "#include \"{}\"", include);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cython {
|
||||
for (module, names) in &self.config.cython.cimports {
|
||||
write!(out, "from {} cimport {}", module, names.join(", "));
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref line) = self.config.after_includes {
|
||||
write!(out, "{}", line);
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write<F: Write>(&self, file: F) {
|
||||
let mut out = SourceWriter::new(file, self);
|
||||
|
||||
self.write_headers(&mut out);
|
||||
|
||||
self.open_namespaces(&mut out);
|
||||
|
||||
for constant in &self.constants {
|
||||
if constant.uses_only_primitive_types() {
|
||||
out.new_line_if_not_start();
|
||||
constant.write(&self.config, &mut out, None);
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
for item in &self.items {
|
||||
if item
|
||||
.deref()
|
||||
.annotations()
|
||||
.bool("no-export")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
out.new_line_if_not_start();
|
||||
match *item {
|
||||
ItemContainer::Constant(..) => unreachable!(),
|
||||
ItemContainer::Static(..) => unreachable!(),
|
||||
ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
|
||||
ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
|
||||
ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
|
||||
ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
|
||||
ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
|
||||
}
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
for constant in &self.constants {
|
||||
if !constant.uses_only_primitive_types() {
|
||||
out.new_line_if_not_start();
|
||||
constant.write(&self.config, &mut out, None);
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
if !self.functions.is_empty() || !self.globals.is_empty() {
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#ifdef __cplusplus");
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx {
|
||||
if let Some(ref using_namespaces) = self.config.using_namespaces {
|
||||
for namespace in using_namespaces {
|
||||
out.new_line();
|
||||
write!(out, "using namespace {};", namespace);
|
||||
}
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx || self.config.cpp_compatible_c() {
|
||||
out.new_line();
|
||||
out.write("extern \"C\" {");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
for global in &self.globals {
|
||||
out.new_line_if_not_start();
|
||||
global.write(&self.config, &mut out);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
for function in &self.functions {
|
||||
out.new_line_if_not_start();
|
||||
function.write(&self.config, &mut out);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.new_line();
|
||||
out.write("#ifdef __cplusplus");
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx || self.config.cpp_compatible_c() {
|
||||
out.new_line();
|
||||
out.write("} // extern \"C\"");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cython
|
||||
&& self.globals.is_empty()
|
||||
&& self.constants.is_empty()
|
||||
&& self.items.is_empty()
|
||||
&& self.functions.is_empty()
|
||||
{
|
||||
out.write("pass");
|
||||
}
|
||||
|
||||
self.close_namespaces(&mut out);
|
||||
|
||||
if let Some(f) = self.config.include_guard() {
|
||||
out.new_line_if_not_start();
|
||||
if self.config.language == Language::C {
|
||||
write!(out, "#endif /* {} */", f);
|
||||
} else {
|
||||
write!(out, "#endif // {}", f);
|
||||
}
|
||||
out.new_line();
|
||||
}
|
||||
if let Some(ref f) = self.config.trailer {
|
||||
out.new_line_if_not_start();
|
||||
write!(out, "{}", f);
|
||||
if !f.ends_with('\n') {
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn all_namespaces(&self) -> Vec<&str> {
|
||||
if self.config.language != Language::Cxx && !self.config.cpp_compatible_c() {
|
||||
return vec![];
|
||||
}
|
||||
let mut ret = vec![];
|
||||
if let Some(ref namespace) = self.config.namespace {
|
||||
ret.push(&**namespace);
|
||||
}
|
||||
if let Some(ref namespaces) = self.config.namespaces {
|
||||
for namespace in namespaces {
|
||||
ret.push(&**namespace);
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
fn open_close_namespaces<F: Write>(&self, op: NamespaceOperation, out: &mut SourceWriter<F>) {
|
||||
if self.config.language == Language::Cython {
|
||||
if op == NamespaceOperation::Open {
|
||||
out.new_line();
|
||||
let header = self.config.cython.header.as_deref().unwrap_or("*");
|
||||
write!(out, "cdef extern from {}", header);
|
||||
out.open_brace();
|
||||
} else {
|
||||
out.close_brace(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let mut namespaces = self.all_namespaces();
|
||||
if namespaces.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if op == NamespaceOperation::Close {
|
||||
namespaces.reverse();
|
||||
}
|
||||
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#ifdef __cplusplus");
|
||||
}
|
||||
|
||||
for namespace in namespaces {
|
||||
out.new_line();
|
||||
match op {
|
||||
NamespaceOperation::Open => write!(out, "namespace {} {{", namespace),
|
||||
NamespaceOperation::Close => write!(out, "}} // namespace {}", namespace),
|
||||
}
|
||||
}
|
||||
|
||||
out.new_line();
|
||||
if self.config.cpp_compatible_c() {
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn open_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
|
||||
self.open_close_namespaces(NamespaceOperation::Open, out);
|
||||
}
|
||||
|
||||
pub(crate) fn close_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
|
||||
self.open_close_namespaces(NamespaceOperation::Close, out);
|
||||
}
|
||||
}
|
||||
138
zeroidc/vendor/cbindgen/src/bindgen/bitflags.rs
vendored
Normal file
138
zeroidc/vendor/cbindgen/src/bindgen/bitflags.rs
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 proc_macro2::TokenStream;
|
||||
use syn::parse::{Parse, ParseStream, Parser, Result as ParseResult};
|
||||
|
||||
// $(#[$outer:meta])*
|
||||
// ($($vis:tt)*) $BitFlags:ident: $T:ty {
|
||||
// $(
|
||||
// $(#[$inner:ident $($args:tt)*])*
|
||||
// const $Flag:ident = $value:expr;
|
||||
// )+
|
||||
// }
|
||||
#[derive(Debug)]
|
||||
pub struct Bitflags {
|
||||
attrs: Vec<syn::Attribute>,
|
||||
vis: syn::Visibility,
|
||||
struct_token: Token![struct],
|
||||
name: syn::Ident,
|
||||
colon_token: Token![:],
|
||||
repr: syn::Type,
|
||||
flags: Flags,
|
||||
}
|
||||
|
||||
impl Bitflags {
|
||||
pub fn expand(&self) -> (syn::ItemStruct, syn::ItemImpl) {
|
||||
let Bitflags {
|
||||
ref attrs,
|
||||
ref vis,
|
||||
ref name,
|
||||
ref repr,
|
||||
ref flags,
|
||||
..
|
||||
} = *self;
|
||||
|
||||
let struct_ = parse_quote! {
|
||||
/// cbindgen:internal-derive-bitflags=true
|
||||
#(#attrs)*
|
||||
#vis struct #name {
|
||||
bits: #repr,
|
||||
}
|
||||
};
|
||||
|
||||
let consts = flags.expand(name, repr);
|
||||
let impl_ = parse_quote! {
|
||||
impl #name {
|
||||
#consts
|
||||
}
|
||||
};
|
||||
|
||||
(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()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// $(#[$inner:ident $($args:tt)*])*
|
||||
// const $Flag:ident = $value:expr;
|
||||
#[derive(Debug)]
|
||||
struct Flag {
|
||||
attrs: Vec<syn::Attribute>,
|
||||
const_token: Token![const],
|
||||
name: syn::Ident,
|
||||
equals_token: Token![=],
|
||||
value: syn::Expr,
|
||||
semicolon_token: Token![;],
|
||||
}
|
||||
|
||||
impl Flag {
|
||||
fn expand(&self, struct_name: &syn::Ident, repr: &syn::Type) -> TokenStream {
|
||||
let Flag {
|
||||
ref attrs,
|
||||
ref name,
|
||||
ref value,
|
||||
..
|
||||
} = *self;
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
pub const #name : #struct_name = #struct_name { bits: (#value) as #repr };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Flag {
|
||||
fn parse(input: ParseStream) -> ParseResult<Self> {
|
||||
Ok(Self {
|
||||
attrs: input.call(syn::Attribute::parse_outer)?,
|
||||
const_token: input.parse()?,
|
||||
name: input.parse()?,
|
||||
equals_token: input.parse()?,
|
||||
value: input.parse()?,
|
||||
semicolon_token: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Flags(Vec<Flag>);
|
||||
|
||||
impl Parse for Flags {
|
||||
fn parse(input: ParseStream) -> ParseResult<Self> {
|
||||
let content;
|
||||
let _ = braced!(content in input);
|
||||
let mut flags = vec![];
|
||||
while !content.is_empty() {
|
||||
flags.push(content.parse()?);
|
||||
}
|
||||
Ok(Flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
fn expand(&self, struct_name: &syn::Ident, repr: &syn::Type) -> TokenStream {
|
||||
let mut ts = quote! {};
|
||||
for flag in &self.0 {
|
||||
ts.extend(flag.expand(struct_name, repr));
|
||||
}
|
||||
ts
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(tokens: TokenStream) -> ParseResult<Bitflags> {
|
||||
let parser = Bitflags::parse;
|
||||
parser.parse2(tokens)
|
||||
}
|
||||
396
zeroidc/vendor/cbindgen/src/bindgen/builder.rs
vendored
Normal file
396
zeroidc/vendor/cbindgen/src/bindgen/builder.rs
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::path;
|
||||
|
||||
use crate::bindgen::bindings::Bindings;
|
||||
use crate::bindgen::cargo::Cargo;
|
||||
use crate::bindgen::config::{Braces, Config, Language, Profile, Style};
|
||||
use crate::bindgen::error::Error;
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::parser::{self, Parse};
|
||||
|
||||
/// A builder for generating a bindings header.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Builder {
|
||||
config: Config,
|
||||
srcs: Vec<path::PathBuf>,
|
||||
lib: Option<(path::PathBuf, Option<String>)>,
|
||||
lib_cargo: Option<Cargo>,
|
||||
std_types: bool,
|
||||
lockfile: Option<path::PathBuf>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Builder {
|
||||
Builder {
|
||||
config: Config::default(),
|
||||
srcs: Vec::new(),
|
||||
lib: None,
|
||||
lib_cargo: None,
|
||||
std_types: true,
|
||||
lockfile: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_header<S: AsRef<str>>(mut self, header: S) -> Builder {
|
||||
self.config.header = Some(String::from(header.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_no_includes(mut self) -> Builder {
|
||||
self.config.no_includes = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_include<S: AsRef<str>>(mut self, include: S) -> Builder {
|
||||
self.config.includes.push(String::from(include.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_sys_include<S: AsRef<str>>(mut self, include: S) -> Builder {
|
||||
self.config
|
||||
.sys_includes
|
||||
.push(String::from(include.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_after_include<S: AsRef<str>>(mut self, line: S) -> Builder {
|
||||
self.config.after_includes = Some(String::from(line.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_trailer<S: AsRef<str>>(mut self, trailer: S) -> Builder {
|
||||
self.config.trailer = Some(String::from(trailer.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_include_guard<S: AsRef<str>>(mut self, include_guard: S) -> Builder {
|
||||
self.config.include_guard = Some(String::from(include_guard.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_pragma_once(mut self, pragma_once: bool) -> Builder {
|
||||
self.config.pragma_once = pragma_once;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_autogen_warning<S: AsRef<str>>(mut self, autogen_warning: S) -> Builder {
|
||||
self.config.autogen_warning = Some(String::from(autogen_warning.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_include_version(mut self, include_version: bool) -> Builder {
|
||||
self.config.include_version = include_version;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_namespace<S: AsRef<str>>(mut self, namespace: S) -> Builder {
|
||||
self.config.namespace = Some(String::from(namespace.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder {
|
||||
self.config.namespaces = Some(
|
||||
namespaces
|
||||
.iter()
|
||||
.map(|x| String::from(x.as_ref()))
|
||||
.collect(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_using_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder {
|
||||
self.config.using_namespaces = Some(
|
||||
namespaces
|
||||
.iter()
|
||||
.map(|x| String::from(x.as_ref()))
|
||||
.collect(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_braces(mut self, braces: Braces) -> Builder {
|
||||
self.config.braces = braces;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_line_length(mut self, line_length: usize) -> Builder {
|
||||
self.config.line_length = line_length;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_tab_width(mut self, tab_width: usize) -> Builder {
|
||||
self.config.tab_width = tab_width;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_language(mut self, language: Language) -> Builder {
|
||||
self.config.language = language;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_style(mut self, style: Style) -> Builder {
|
||||
self.config.style = style;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
|
||||
self.config
|
||||
.export
|
||||
.include
|
||||
.push(String::from(item_name.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
|
||||
self.config
|
||||
.export
|
||||
.exclude
|
||||
.push(String::from(item_name.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
|
||||
self.config
|
||||
.export
|
||||
.rename
|
||||
.insert(String::from(from.as_ref()), String::from(to.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
|
||||
self.config.export.prefix = Some(String::from(prefix.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
|
||||
self.config.parse.parse_deps = parse_deps;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_include<S: AsRef<str>>(mut self, include: &[S]) -> Builder {
|
||||
self.config.parse.include =
|
||||
Some(include.iter().map(|x| String::from(x.as_ref())).collect());
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_exclude<S: AsRef<str>>(mut self, exclude: &[S]) -> Builder {
|
||||
self.config.parse.exclude = exclude.iter().map(|x| String::from(x.as_ref())).collect();
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_expand<S: AsRef<str>>(mut self, expand: &[S]) -> Builder {
|
||||
self.config.parse.expand.crates = expand.iter().map(|x| String::from(x.as_ref())).collect();
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_expand_all_features(mut self, expand_all_features: bool) -> Builder {
|
||||
self.config.parse.expand.all_features = expand_all_features;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_expand_default_features(mut self, expand_default_features: bool) -> Builder {
|
||||
self.config.parse.expand.default_features = expand_default_features;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_expand_features<S: AsRef<str>>(mut self, expand_features: &[S]) -> Builder {
|
||||
self.config.parse.expand.features = Some(
|
||||
expand_features
|
||||
.iter()
|
||||
.map(|x| String::from(x.as_ref()))
|
||||
.collect(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_expand_profile(mut self, profile: Profile) -> Builder {
|
||||
self.config.parse.expand.profile = profile;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_extra_bindings<S: AsRef<str>>(mut self, extra_bindings: &[S]) -> Builder {
|
||||
self.config.parse.extra_bindings = extra_bindings
|
||||
.iter()
|
||||
.map(|x| String::from(x.as_ref()))
|
||||
.collect();
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_only_target_dependencies(mut self, only_target_dependencies: bool) -> Builder {
|
||||
self.config.only_target_dependencies = only_target_dependencies;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_documentation(mut self, documentation: bool) -> Builder {
|
||||
self.config.documentation = documentation;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_target_os_define(mut self, platform: &str, preprocessor_define: &str) -> Builder {
|
||||
self.config.defines.insert(
|
||||
format!("target_os = {}", platform),
|
||||
preprocessor_define.to_owned(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_define(mut self, key: &str, value: &str, preprocessor_define: &str) -> Builder {
|
||||
self.config.defines.insert(
|
||||
format!("{} = {}", key, value),
|
||||
preprocessor_define.to_owned(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_config(mut self, config: Config) -> Builder {
|
||||
self.config = config;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_std_types(mut self, std_types: bool) -> Builder {
|
||||
self.std_types = std_types;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_src<P: AsRef<path::Path>>(mut self, src: P) -> Builder {
|
||||
self.srcs.push(src.as_ref().to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_crate<P: AsRef<path::Path>>(mut self, lib_dir: P) -> Builder {
|
||||
debug_assert!(self.lib.is_none());
|
||||
debug_assert!(self.lib_cargo.is_none());
|
||||
self.lib = Some((path::PathBuf::from(lib_dir.as_ref()), None));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_crate_and_name<P: AsRef<path::Path>, S: AsRef<str>>(
|
||||
mut self,
|
||||
lib_dir: P,
|
||||
binding_lib_name: S,
|
||||
) -> Builder {
|
||||
debug_assert!(self.lib.is_none());
|
||||
debug_assert!(self.lib_cargo.is_none());
|
||||
self.lib = Some((
|
||||
path::PathBuf::from(lib_dir.as_ref()),
|
||||
Some(String::from(binding_lib_name.as_ref())),
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn with_cargo(mut self, lib: Cargo) -> Builder {
|
||||
debug_assert!(self.lib.is_none());
|
||||
debug_assert!(self.lib_cargo.is_none());
|
||||
self.lib_cargo = Some(lib);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_lockfile<P: AsRef<path::Path>>(mut self, lockfile: P) -> Builder {
|
||||
debug_assert!(self.lockfile.is_none());
|
||||
debug_assert!(self.lib_cargo.is_none());
|
||||
self.lockfile = Some(path::PathBuf::from(lockfile.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn generate(self) -> Result<Bindings, Error> {
|
||||
let mut result = Parse::new();
|
||||
|
||||
if self.std_types {
|
||||
result.add_std_types();
|
||||
}
|
||||
|
||||
for x in &self.srcs {
|
||||
result.extend_with(&parser::parse_src(x, &self.config)?);
|
||||
}
|
||||
|
||||
if let Some((lib_dir, binding_lib_name)) = self.lib.clone() {
|
||||
let lockfile = self.lockfile.as_ref().and_then(|p| p.to_str());
|
||||
|
||||
let cargo = Cargo::load(
|
||||
&lib_dir,
|
||||
lockfile,
|
||||
binding_lib_name.as_deref(),
|
||||
self.config.parse.parse_deps,
|
||||
self.config.parse.clean,
|
||||
self.config.only_target_dependencies,
|
||||
/* existing_metadata = */ None,
|
||||
)?;
|
||||
|
||||
result.extend_with(&parser::parse_lib(cargo, &self.config)?);
|
||||
} else if let Some(cargo) = self.lib_cargo.clone() {
|
||||
result.extend_with(&parser::parse_lib(cargo, &self.config)?);
|
||||
}
|
||||
|
||||
Library::new(
|
||||
self.config,
|
||||
result.constants,
|
||||
result.globals,
|
||||
result.enums,
|
||||
result.structs,
|
||||
result.unions,
|
||||
result.opaque_items,
|
||||
result.typedefs,
|
||||
result.functions,
|
||||
)
|
||||
.generate()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn with_style() {
|
||||
assert_eq!(
|
||||
Style::Tag,
|
||||
Builder::new().with_style(Style::Tag).config.style
|
||||
);
|
||||
}
|
||||
}
|
||||
252
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo.rs
vendored
Normal file
252
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo.rs
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::path::{Path, PathBuf};
|
||||
|
||||
use crate::bindgen::cargo::cargo_expand;
|
||||
use crate::bindgen::cargo::cargo_lock::{self, Lock};
|
||||
pub(crate) use crate::bindgen::cargo::cargo_metadata::PackageRef;
|
||||
use crate::bindgen::cargo::cargo_metadata::{self, Metadata};
|
||||
use crate::bindgen::cargo::cargo_toml;
|
||||
use crate::bindgen::config::Profile;
|
||||
use crate::bindgen::error::Error;
|
||||
use crate::bindgen::ir::Cfg;
|
||||
|
||||
/// Parse a dependency string used in Cargo.lock
|
||||
fn parse_dep_string(dep_string: &str) -> (&str, Option<&str>) {
|
||||
let split: Vec<&str> = dep_string.split_whitespace().collect();
|
||||
|
||||
(split[0], split.get(1).cloned())
|
||||
}
|
||||
|
||||
/// A collection of metadata for a library from cargo.
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Cargo {
|
||||
manifest_path: PathBuf,
|
||||
binding_crate_name: String,
|
||||
lock: Option<Lock>,
|
||||
metadata: Metadata,
|
||||
clean: bool,
|
||||
}
|
||||
|
||||
impl Cargo {
|
||||
/// Gather metadata from cargo for a specific library and binding crate
|
||||
/// name. If dependency finding isn't needed then Cargo.lock files don't
|
||||
/// need to be parsed.
|
||||
pub(crate) fn load(
|
||||
crate_dir: &Path,
|
||||
lock_file: Option<&str>,
|
||||
binding_crate_name: Option<&str>,
|
||||
use_cargo_lock: bool,
|
||||
clean: bool,
|
||||
only_target_dependencies: bool,
|
||||
existing_metadata_file: Option<&Path>,
|
||||
) -> Result<Cargo, Error> {
|
||||
let toml_path = crate_dir.join("Cargo.toml");
|
||||
let metadata =
|
||||
cargo_metadata::metadata(&toml_path, existing_metadata_file, only_target_dependencies)
|
||||
.map_err(|x| Error::CargoMetadata(toml_path.to_str().unwrap().to_owned(), x))?;
|
||||
let lock_path = lock_file
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| Path::new(&metadata.workspace_root).join("Cargo.lock"));
|
||||
|
||||
let lock = if use_cargo_lock {
|
||||
match cargo_lock::lock(&lock_path) {
|
||||
Ok(lock) => Some(lock),
|
||||
Err(x) => {
|
||||
warn!("Couldn't load lock file {:?}: {:?}", lock_path, x);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Use the specified binding crate name or infer it from the manifest
|
||||
let binding_crate_name = match binding_crate_name {
|
||||
Some(s) => s.to_owned(),
|
||||
None => {
|
||||
let manifest = cargo_toml::manifest(&toml_path)
|
||||
.map_err(|x| Error::CargoToml(toml_path.to_str().unwrap().to_owned(), x))?;
|
||||
manifest.package.name
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Cargo {
|
||||
manifest_path: toml_path,
|
||||
binding_crate_name,
|
||||
lock,
|
||||
metadata,
|
||||
clean,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn binding_crate_name(&self) -> &str {
|
||||
&self.binding_crate_name
|
||||
}
|
||||
|
||||
pub(crate) fn binding_crate_ref(&self) -> PackageRef {
|
||||
match self.find_pkg_ref(&self.binding_crate_name) {
|
||||
Some(pkg_ref) => pkg_ref,
|
||||
None => panic!(
|
||||
"Unable to find {} for {:?}",
|
||||
self.binding_crate_name, self.manifest_path
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dependencies(&self, package: &PackageRef) -> Vec<(PackageRef, Option<Cfg>)> {
|
||||
let lock = match self.lock {
|
||||
Some(ref lock) => lock,
|
||||
None => return vec![],
|
||||
};
|
||||
|
||||
let mut dependencies = None;
|
||||
|
||||
// Find the dependencies listing in the lockfile
|
||||
if let Some(ref root) = lock.root {
|
||||
// If the version is not on the lockfile then it shouldn't be
|
||||
// ambiguous.
|
||||
if root.name == package.name
|
||||
&& package
|
||||
.version
|
||||
.as_ref()
|
||||
.map_or(true, |v| *v == root.version)
|
||||
{
|
||||
dependencies = root.dependencies.as_ref();
|
||||
}
|
||||
}
|
||||
if dependencies.is_none() {
|
||||
if let Some(ref lock_packages) = lock.package {
|
||||
for lock_package in lock_packages {
|
||||
if lock_package.name == package.name
|
||||
&& package
|
||||
.version
|
||||
.as_ref()
|
||||
.map_or(true, |v| *v == lock_package.version)
|
||||
{
|
||||
dependencies = lock_package.dependencies.as_ref();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if dependencies.is_none() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
dependencies
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|dep| {
|
||||
let (dep_name, dep_version) = parse_dep_string(dep);
|
||||
|
||||
// If a version was not specified find the only package with the name of the dependency
|
||||
let dep_version = dep_version.or_else(|| {
|
||||
let mut versions = self.metadata.packages.iter().filter_map(|package| {
|
||||
if package.name_and_version.name != dep_name {
|
||||
return None;
|
||||
}
|
||||
package.name_and_version.version.as_deref()
|
||||
});
|
||||
|
||||
// If the iterator contains more items, meaning multiple versions of the same
|
||||
// package are present, warn! amd abort.
|
||||
let version = versions.next();
|
||||
if versions.next().is_none() {
|
||||
version
|
||||
} else {
|
||||
warn!("when looking for a version for package {}, multiple versions where found", dep_name);
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
// Try to find the cfgs in the Cargo.toml
|
||||
let cfg = self
|
||||
.metadata
|
||||
.packages
|
||||
.get(package)
|
||||
.and_then(|meta_package| meta_package.dependencies.get(dep_name))
|
||||
.and_then(|meta_dep| Cfg::load_metadata(meta_dep));
|
||||
|
||||
let package_ref = PackageRef {
|
||||
name: dep_name.to_owned(),
|
||||
version: dep_version.map(|v| v.to_owned()),
|
||||
};
|
||||
|
||||
(package_ref, cfg)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Finds the package reference in `cargo metadata` that has `package_name`
|
||||
/// ignoring the version.
|
||||
fn find_pkg_ref(&self, package_name: &str) -> Option<PackageRef> {
|
||||
for package in &self.metadata.packages {
|
||||
if package.name_and_version.name == package_name {
|
||||
return Some(package.name_and_version.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Finds the directory for a specified package reference.
|
||||
#[allow(unused)]
|
||||
pub(crate) fn find_crate_dir(&self, package: &PackageRef) -> Option<PathBuf> {
|
||||
self.metadata
|
||||
.packages
|
||||
.get(package)
|
||||
.and_then(|meta_package| {
|
||||
Path::new(&meta_package.manifest_path)
|
||||
.parent()
|
||||
.map(|x| x.to_owned())
|
||||
})
|
||||
}
|
||||
|
||||
/// Finds `src/lib.rs` for a specified package reference.
|
||||
pub(crate) fn find_crate_src(&self, package: &PackageRef) -> Option<PathBuf> {
|
||||
let kind_lib = String::from("lib");
|
||||
let kind_staticlib = String::from("staticlib");
|
||||
let kind_rlib = String::from("rlib");
|
||||
let kind_cdylib = String::from("cdylib");
|
||||
let kind_dylib = String::from("dylib");
|
||||
|
||||
self.metadata
|
||||
.packages
|
||||
.get(package)
|
||||
.and_then(|meta_package| {
|
||||
for target in &meta_package.targets {
|
||||
if target.kind.contains(&kind_lib)
|
||||
|| target.kind.contains(&kind_staticlib)
|
||||
|| target.kind.contains(&kind_rlib)
|
||||
|| target.kind.contains(&kind_cdylib)
|
||||
|| target.kind.contains(&kind_dylib)
|
||||
{
|
||||
return Some(PathBuf::from(&target.src_path));
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expand_crate(
|
||||
&self,
|
||||
package: &PackageRef,
|
||||
expand_all_features: bool,
|
||||
expand_default_features: bool,
|
||||
expand_features: &Option<Vec<String>>,
|
||||
profile: Profile,
|
||||
) -> Result<String, cargo_expand::Error> {
|
||||
cargo_expand::expand(
|
||||
&self.manifest_path,
|
||||
&package.name,
|
||||
package.version.as_deref(),
|
||||
self.clean,
|
||||
expand_all_features,
|
||||
expand_default_features,
|
||||
expand_features,
|
||||
profile,
|
||||
)
|
||||
}
|
||||
}
|
||||
145
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_expand.rs
vendored
Normal file
145
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_expand.rs
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 crate::bindgen::config::Profile;
|
||||
use std::env;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str::{from_utf8, Utf8Error};
|
||||
|
||||
extern crate tempfile;
|
||||
use self::tempfile::Builder;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Possible errors that can occur during `rustc -Zunpretty=expanded`.
|
||||
pub enum Error {
|
||||
/// Error during creation of temporary directory
|
||||
Io(io::Error),
|
||||
/// Output of `cargo metadata` was not valid utf8
|
||||
Utf8(Utf8Error),
|
||||
/// Error during execution of `cargo rustc -Zunpretty=expanded`
|
||||
Compile(String),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<Utf8Error> for Error {
|
||||
fn from(err: Utf8Error) -> Self {
|
||||
Error::Utf8(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::Io(ref err) => err.fmt(f),
|
||||
Error::Utf8(ref err) => err.fmt(f),
|
||||
Error::Compile(ref err) => write!(f, "{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Error::Io(ref err) => Some(err),
|
||||
Error::Utf8(ref err) => Some(err),
|
||||
Error::Compile(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Use rustc to expand and pretty print the crate into a single file,
|
||||
/// removing any macros in the process.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn expand(
|
||||
manifest_path: &Path,
|
||||
crate_name: &str,
|
||||
version: Option<&str>,
|
||||
use_tempdir: bool,
|
||||
expand_all_features: bool,
|
||||
expand_default_features: bool,
|
||||
expand_features: &Option<Vec<String>>,
|
||||
profile: Profile,
|
||||
) -> Result<String, Error> {
|
||||
let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
|
||||
let mut cmd = Command::new(cargo);
|
||||
|
||||
let mut _temp_dir = None; // drop guard
|
||||
if use_tempdir {
|
||||
_temp_dir = Some(Builder::new().prefix("cbindgen-expand").tempdir()?);
|
||||
cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
|
||||
} else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
|
||||
cmd.env("CARGO_TARGET_DIR", path);
|
||||
} else if let Ok(ref path) = env::var("OUT_DIR") {
|
||||
// When cbindgen was started programatically from a build.rs file, Cargo is running and
|
||||
// locking the default target directory. In this case we need to use another directory,
|
||||
// else we would end up in a deadlock. If Cargo is running `OUT_DIR` will be set, so we
|
||||
// can use a directory relative to that.
|
||||
cmd.env("CARGO_TARGET_DIR", PathBuf::from(path).join("expanded"));
|
||||
}
|
||||
|
||||
// Set this variable so that we don't call it recursively if we expand a crate that is using
|
||||
// cbindgen
|
||||
cmd.env("_CBINDGEN_IS_RUNNING", "1");
|
||||
|
||||
cmd.arg("rustc");
|
||||
cmd.arg("--lib");
|
||||
// When build with the release profile we can't choose the `check` profile.
|
||||
if profile != Profile::Release {
|
||||
cmd.arg("--profile=check");
|
||||
}
|
||||
cmd.arg("--manifest-path");
|
||||
cmd.arg(manifest_path);
|
||||
if let Some(features) = expand_features {
|
||||
cmd.arg("--features");
|
||||
let mut features_str = String::new();
|
||||
for (index, feature) in features.iter().enumerate() {
|
||||
if index != 0 {
|
||||
features_str.push(' ');
|
||||
}
|
||||
features_str.push_str(feature);
|
||||
}
|
||||
cmd.arg(features_str);
|
||||
}
|
||||
if expand_all_features {
|
||||
cmd.arg("--all-features");
|
||||
}
|
||||
if !expand_default_features {
|
||||
cmd.arg("--no-default-features");
|
||||
}
|
||||
match profile {
|
||||
Profile::Debug => {}
|
||||
Profile::Release => {
|
||||
cmd.arg("--release");
|
||||
}
|
||||
}
|
||||
cmd.arg("-p");
|
||||
let mut package = crate_name.to_owned();
|
||||
if let Some(version) = version {
|
||||
package.push(':');
|
||||
package.push_str(version);
|
||||
}
|
||||
cmd.arg(&package);
|
||||
cmd.arg("--verbose");
|
||||
cmd.arg("--");
|
||||
cmd.arg("-Zunpretty=expanded");
|
||||
info!("Command: {:?}", cmd);
|
||||
let output = cmd.output()?;
|
||||
|
||||
let src = from_utf8(&output.stdout)?.to_owned();
|
||||
let error = from_utf8(&output.stderr)?.to_owned();
|
||||
|
||||
if src.is_empty() {
|
||||
Err(Error::Compile(error))
|
||||
} else {
|
||||
Ok(src)
|
||||
}
|
||||
}
|
||||
51
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_lock.rs
vendored
Normal file
51
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_lock.rs
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Possible errors that can occur during Cargo.toml parsing.
|
||||
pub enum Error {
|
||||
/// Error during reading of Cargo.toml
|
||||
Io(io::Error),
|
||||
/// Deserialization error
|
||||
Toml(toml::de::Error),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<toml::de::Error> for Error {
|
||||
fn from(err: toml::de::Error) -> Self {
|
||||
Error::Toml(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Lock {
|
||||
pub root: Option<Package>,
|
||||
pub package: Option<Vec<Package>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Package {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
/// A list of dependencies formatted like "NAME VERSION-OPT REGISTRY-OPT"
|
||||
pub dependencies: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Parse the Cargo.toml for a given path
|
||||
pub fn lock(manifest_path: &Path) -> Result<Lock, Error> {
|
||||
let mut s = String::new();
|
||||
let mut f = File::open(manifest_path)?;
|
||||
f.read_to_string(&mut s)?;
|
||||
|
||||
toml::from_str::<Lock>(&s).map_err(|x| x.into())
|
||||
}
|
||||
257
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_metadata.rs
vendored
Normal file
257
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_metadata.rs
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
#![deny(missing_docs)]
|
||||
//! Structured access to the output of `cargo metadata`
|
||||
//! Usually used from within a `cargo-*` executable
|
||||
|
||||
// Forked from `https://github.com/oli-obk/cargo_metadata`
|
||||
// Modifications:
|
||||
// 1. Remove `resolve` from Metadata because it was causing parse failures
|
||||
// 2. Fix the `manifest-path` argument
|
||||
// 3. Add `--all-features` argument
|
||||
// 4. Remove the `--no-deps` argument
|
||||
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output};
|
||||
use std::str::Utf8Error;
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
/// Starting point for metadata returned by `cargo metadata`
|
||||
pub struct Metadata {
|
||||
/// A list of all crates referenced by this crate (and the crate itself)
|
||||
pub packages: HashSet<Package>,
|
||||
version: usize,
|
||||
/// path to the workspace containing the `Cargo.lock`
|
||||
pub workspace_root: String,
|
||||
}
|
||||
|
||||
/// A reference to a package including it's name and the specific version.
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PackageRef {
|
||||
pub name: String,
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
/// A crate
|
||||
pub struct Package {
|
||||
#[serde(flatten)]
|
||||
pub name_and_version: PackageRef,
|
||||
id: String,
|
||||
source: Option<String>,
|
||||
/// List of dependencies of this particular package
|
||||
pub dependencies: HashSet<Dependency>,
|
||||
/// Targets provided by the crate (lib, bin, example, test, ...)
|
||||
pub targets: Vec<Target>,
|
||||
features: HashMap<String, Vec<String>>,
|
||||
/// path containing the `Cargo.toml`
|
||||
pub manifest_path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
/// A dependency of the main crate
|
||||
pub struct Dependency {
|
||||
/// Name as given in the `Cargo.toml`
|
||||
pub name: String,
|
||||
source: Option<String>,
|
||||
/// Whether this is required or optional
|
||||
pub req: String,
|
||||
kind: Option<String>,
|
||||
optional: bool,
|
||||
uses_default_features: bool,
|
||||
features: Vec<String>,
|
||||
pub target: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
/// A single target (lib, bin, example, ...) provided by a crate
|
||||
pub struct Target {
|
||||
/// Name as given in the `Cargo.toml` or generated from the file name
|
||||
pub name: String,
|
||||
/// Kind of target ("bin", "example", "test", "bench", "lib")
|
||||
pub kind: Vec<String>,
|
||||
/// Almost the same as `kind`, except when an example is a library instad of an executable.
|
||||
/// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
|
||||
#[serde(default)]
|
||||
pub crate_types: Vec<String>,
|
||||
/// Path to the main source file of the target
|
||||
pub src_path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Possible errors that can occur during metadata parsing.
|
||||
pub enum Error {
|
||||
/// Error during execution of `cargo metadata`
|
||||
Io(io::Error),
|
||||
/// Metadata extraction failure
|
||||
Metadata(Output),
|
||||
/// Output of `cargo metadata` was not valid utf8
|
||||
Utf8(Utf8Error),
|
||||
/// Deserialization error (structure of json did not match expected structure)
|
||||
Json(serde_json::Error),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<Utf8Error> for Error {
|
||||
fn from(err: Utf8Error) -> Self {
|
||||
Error::Utf8(err)
|
||||
}
|
||||
}
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
Error::Json(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::Io(ref err) => err.fmt(f),
|
||||
Error::Metadata(_) => write!(f, "Metadata error"),
|
||||
Error::Utf8(ref err) => err.fmt(f),
|
||||
Error::Json(ref err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Error::Io(ref err) => Some(err),
|
||||
Error::Metadata(_) => None,
|
||||
Error::Utf8(ref err) => Some(err),
|
||||
Error::Json(ref err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementations that let us lookup Packages and Dependencies by name (string)
|
||||
|
||||
impl Borrow<PackageRef> for Package {
|
||||
fn borrow(&self) -> &PackageRef {
|
||||
&self.name_and_version
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Package {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name_and_version.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Package {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name_and_version == other.name_and_version
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Package {}
|
||||
|
||||
impl Borrow<str> for Dependency {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Dependency {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Dependency {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Dependency {}
|
||||
|
||||
fn discover_target(manifest_path: &Path) -> Option<String> {
|
||||
if let Ok(target) = std::env::var("TARGET") {
|
||||
return Some(target);
|
||||
}
|
||||
|
||||
// We must be running as a standalone script, not under cargo.
|
||||
// Let's use the host platform instead.
|
||||
// We figure out the host platform through rustc and use that.
|
||||
// We unfortunatelly cannot go through cargo, since cargo rustc _also_ builds.
|
||||
// If `rustc` fails to run, we just fall back to not passing --filter-platforms.
|
||||
//
|
||||
// NOTE: We set the current directory in case of rustup shenanigans.
|
||||
let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc"));
|
||||
debug!("Discovering host platform by {:?}", rustc);
|
||||
|
||||
let rustc_output = Command::new(rustc)
|
||||
.current_dir(manifest_path.parent().unwrap())
|
||||
.arg("-vV")
|
||||
.output();
|
||||
let rustc_output = match rustc_output {
|
||||
Ok(ref out) => String::from_utf8_lossy(&out.stdout),
|
||||
Err(..) => return None,
|
||||
};
|
||||
|
||||
let field = "host: ";
|
||||
rustc_output.lines().find_map(|l| {
|
||||
// XXX l.strip_prefix(field) re-implemented to preserve MSRV
|
||||
if l.starts_with(field) {
|
||||
Some(l[field.len()..].into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// The main entry point to obtaining metadata
|
||||
pub fn metadata(
|
||||
manifest_path: &Path,
|
||||
existing_metadata_file: Option<&Path>,
|
||||
only_target: bool,
|
||||
) -> Result<Metadata, Error> {
|
||||
let output;
|
||||
let metadata = match existing_metadata_file {
|
||||
Some(path) => Cow::Owned(std::fs::read_to_string(path)?),
|
||||
None => {
|
||||
let target = if only_target {
|
||||
let target = discover_target(manifest_path);
|
||||
if target.is_none() {
|
||||
warn!(
|
||||
"Failed to discover host platform for cargo metadata; \
|
||||
will fetch dependencies for all platforms."
|
||||
);
|
||||
}
|
||||
target
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
|
||||
let mut cmd = Command::new(cargo);
|
||||
cmd.arg("metadata");
|
||||
cmd.arg("--all-features");
|
||||
cmd.arg("--format-version").arg("1");
|
||||
if let Some(target) = target {
|
||||
cmd.arg("--filter-platform").arg(target);
|
||||
}
|
||||
cmd.arg("--manifest-path");
|
||||
cmd.arg(manifest_path);
|
||||
output = cmd.output()?;
|
||||
if !output.status.success() {
|
||||
return Err(Error::Metadata(output));
|
||||
}
|
||||
Cow::Borrowed(std::str::from_utf8(&output.stdout)?)
|
||||
}
|
||||
};
|
||||
|
||||
let meta: Metadata = serde_json::from_str(&*metadata)?;
|
||||
Ok(meta)
|
||||
}
|
||||
67
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_toml.rs
vendored
Normal file
67
zeroidc/vendor/cbindgen/src/bindgen/cargo/cargo_toml.rs
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::error;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Possible errors that can occur during Cargo.toml parsing.
|
||||
pub enum Error {
|
||||
/// Error during reading of Cargo.toml
|
||||
Io(io::Error),
|
||||
/// Deserialization error
|
||||
Toml(toml::de::Error),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
impl From<toml::de::Error> for Error {
|
||||
fn from(err: toml::de::Error) -> Self {
|
||||
Error::Toml(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::Io(ref err) => err.fmt(f),
|
||||
Error::Toml(ref err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Error::Io(ref err) => Some(err),
|
||||
Error::Toml(ref err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Manifest {
|
||||
pub package: Package,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Package {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Parse the Cargo.toml for a given path
|
||||
pub fn manifest(manifest_path: &Path) -> Result<Manifest, Error> {
|
||||
let mut s = String::new();
|
||||
let mut f = File::open(manifest_path)?;
|
||||
f.read_to_string(&mut s)?;
|
||||
|
||||
toml::from_str::<Manifest>(&s).map_err(|x| x.into())
|
||||
}
|
||||
12
zeroidc/vendor/cbindgen/src/bindgen/cargo/mod.rs
vendored
Normal file
12
zeroidc/vendor/cbindgen/src/bindgen/cargo/mod.rs
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#[allow(clippy::module_inception)]
|
||||
mod cargo;
|
||||
pub(crate) mod cargo_expand;
|
||||
pub(crate) mod cargo_lock;
|
||||
pub(crate) mod cargo_metadata;
|
||||
pub(crate) mod cargo_toml;
|
||||
|
||||
pub(crate) use self::cargo::*;
|
||||
325
zeroidc/vendor/cbindgen/src/bindgen/cdecl.rs
vendored
Normal file
325
zeroidc/vendor/cbindgen/src/bindgen/cdecl.rs
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationType;
|
||||
use crate::bindgen::ir::{ArrayLength, Function, Type};
|
||||
use crate::bindgen::writer::{ListType, SourceWriter};
|
||||
use crate::bindgen::{Config, Language};
|
||||
|
||||
// This code is for translating Rust types into C declarations.
|
||||
// See Section 6.7, Declarations, in the C standard for background.
|
||||
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
|
||||
|
||||
enum CDeclarator {
|
||||
Ptr {
|
||||
is_const: bool,
|
||||
is_nullable: bool,
|
||||
is_ref: bool,
|
||||
},
|
||||
Array(String),
|
||||
Func(Vec<(Option<String>, CDecl)>, bool),
|
||||
}
|
||||
|
||||
impl CDeclarator {
|
||||
fn is_ptr(&self) -> bool {
|
||||
match self {
|
||||
CDeclarator::Ptr { .. } | CDeclarator::Func(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CDecl {
|
||||
type_qualifers: String,
|
||||
type_name: String,
|
||||
type_generic_args: Vec<Type>,
|
||||
declarators: Vec<CDeclarator>,
|
||||
type_ctype: Option<DeclarationType>,
|
||||
}
|
||||
|
||||
impl CDecl {
|
||||
fn new() -> CDecl {
|
||||
CDecl {
|
||||
type_qualifers: String::new(),
|
||||
type_name: String::new(),
|
||||
type_generic_args: Vec::new(),
|
||||
declarators: Vec::new(),
|
||||
type_ctype: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_type(t: &Type, config: &Config) -> CDecl {
|
||||
let mut cdecl = CDecl::new();
|
||||
cdecl.build_type(t, false, config);
|
||||
cdecl
|
||||
}
|
||||
|
||||
fn from_func_arg(t: &Type, array_length: Option<&str>, config: &Config) -> CDecl {
|
||||
let mut cdecl = CDecl::new();
|
||||
let length = match array_length {
|
||||
Some(l) => l,
|
||||
None => return CDecl::from_type(t, config),
|
||||
};
|
||||
let (ty, is_const) = match t {
|
||||
Type::Ptr { ty, is_const, .. } => (ty, is_const),
|
||||
_ => unreachable!(
|
||||
"Should never have an array length for a non pointer type {:?}",
|
||||
t
|
||||
),
|
||||
};
|
||||
let ptr_as_array = Type::Array(ty.clone(), ArrayLength::Value(length.to_string()));
|
||||
cdecl.build_type(&ptr_as_array, *is_const, config);
|
||||
cdecl
|
||||
}
|
||||
|
||||
fn from_func(f: &Function, layout_vertical: bool, config: &Config) -> CDecl {
|
||||
let mut cdecl = CDecl::new();
|
||||
cdecl.build_func(f, layout_vertical, config);
|
||||
cdecl
|
||||
}
|
||||
|
||||
fn build_func(&mut self, f: &Function, layout_vertical: bool, config: &Config) {
|
||||
let args = f
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
(
|
||||
arg.name.clone(),
|
||||
CDecl::from_func_arg(&arg.ty, arg.array_length.as_deref(), config),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
self.declarators
|
||||
.push(CDeclarator::Func(args, layout_vertical));
|
||||
self.build_type(&f.ret, false, config);
|
||||
}
|
||||
|
||||
fn build_type(&mut self, t: &Type, is_const: bool, config: &Config) {
|
||||
match t {
|
||||
Type::Path(ref generic) => {
|
||||
if is_const {
|
||||
assert!(
|
||||
self.type_qualifers.is_empty(),
|
||||
"error generating cdecl for {:?}",
|
||||
t
|
||||
);
|
||||
self.type_qualifers = "const".to_owned();
|
||||
}
|
||||
|
||||
assert!(
|
||||
self.type_name.is_empty(),
|
||||
"error generating cdecl for {:?}",
|
||||
t
|
||||
);
|
||||
self.type_name = generic.export_name().to_owned();
|
||||
assert!(
|
||||
self.type_generic_args.is_empty(),
|
||||
"error generating cdecl for {:?}",
|
||||
t
|
||||
);
|
||||
self.type_generic_args = generic.generics().to_owned();
|
||||
self.type_ctype = generic.ctype().cloned();
|
||||
}
|
||||
Type::Primitive(ref p) => {
|
||||
if is_const {
|
||||
assert!(
|
||||
self.type_qualifers.is_empty(),
|
||||
"error generating cdecl for {:?}",
|
||||
t
|
||||
);
|
||||
self.type_qualifers = "const".to_owned();
|
||||
}
|
||||
|
||||
assert!(
|
||||
self.type_name.is_empty(),
|
||||
"error generating cdecl for {:?}",
|
||||
t
|
||||
);
|
||||
self.type_name = p.to_repr_c(config).to_string();
|
||||
}
|
||||
Type::Ptr {
|
||||
ref ty,
|
||||
is_nullable,
|
||||
is_const: ptr_is_const,
|
||||
is_ref,
|
||||
} => {
|
||||
self.declarators.push(CDeclarator::Ptr {
|
||||
is_const,
|
||||
is_nullable: *is_nullable,
|
||||
is_ref: *is_ref,
|
||||
});
|
||||
self.build_type(ty, *ptr_is_const, config);
|
||||
}
|
||||
Type::Array(ref t, ref constant) => {
|
||||
let len = constant.as_str().to_owned();
|
||||
self.declarators.push(CDeclarator::Array(len));
|
||||
self.build_type(t, is_const, config);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref ret,
|
||||
ref args,
|
||||
is_nullable: _,
|
||||
} => {
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|(ref name, ref ty)| (name.clone(), CDecl::from_type(ty, config)))
|
||||
.collect();
|
||||
self.declarators.push(CDeclarator::Ptr {
|
||||
is_const: false,
|
||||
is_nullable: true,
|
||||
is_ref: false,
|
||||
});
|
||||
self.declarators.push(CDeclarator::Func(args, false));
|
||||
self.build_type(ret, false, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write<F: Write>(&self, out: &mut SourceWriter<F>, ident: Option<&str>, config: &Config) {
|
||||
// Write the type-specifier and type-qualifier first
|
||||
if !self.type_qualifers.is_empty() {
|
||||
write!(out, "{} ", self.type_qualifers);
|
||||
}
|
||||
|
||||
if config.language != Language::Cython {
|
||||
if let Some(ref ctype) = self.type_ctype {
|
||||
write!(out, "{} ", ctype.to_str());
|
||||
}
|
||||
}
|
||||
|
||||
write!(out, "{}", self.type_name);
|
||||
|
||||
if !self.type_generic_args.is_empty() {
|
||||
out.write("<");
|
||||
out.write_horizontal_source_list(&self.type_generic_args, ListType::Join(", "));
|
||||
out.write(">");
|
||||
}
|
||||
|
||||
// When we have an identifier, put a space between the type and the declarators
|
||||
if ident.is_some() {
|
||||
out.write(" ");
|
||||
}
|
||||
|
||||
// Write the left part of declarators before the identifier
|
||||
let mut iter_rev = self.declarators.iter().rev().peekable();
|
||||
|
||||
#[allow(clippy::while_let_on_iterator)]
|
||||
while let Some(declarator) = iter_rev.next() {
|
||||
let next_is_pointer = iter_rev.peek().map_or(false, |x| x.is_ptr());
|
||||
|
||||
match *declarator {
|
||||
CDeclarator::Ptr {
|
||||
is_const,
|
||||
is_nullable,
|
||||
is_ref,
|
||||
} => {
|
||||
out.write(if is_ref { "&" } else { "*" });
|
||||
if is_const {
|
||||
out.write("const ");
|
||||
}
|
||||
if !is_nullable && !is_ref && config.language != Language::Cython {
|
||||
if let Some(attr) = &config.pointer.non_null_attribute {
|
||||
write!(out, "{} ", attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
CDeclarator::Array(..) => {
|
||||
if next_is_pointer {
|
||||
out.write("(");
|
||||
}
|
||||
}
|
||||
CDeclarator::Func(..) => {
|
||||
if next_is_pointer {
|
||||
out.write("(");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write the identifier
|
||||
if let Some(ident) = ident {
|
||||
write!(out, "{}", ident);
|
||||
}
|
||||
|
||||
// Write the right part of declarators after the identifier
|
||||
let mut iter = self.declarators.iter();
|
||||
let mut last_was_pointer = false;
|
||||
|
||||
#[allow(clippy::while_let_on_iterator)]
|
||||
while let Some(declarator) = iter.next() {
|
||||
match *declarator {
|
||||
CDeclarator::Ptr { .. } => {
|
||||
last_was_pointer = true;
|
||||
}
|
||||
CDeclarator::Array(ref constant) => {
|
||||
if last_was_pointer {
|
||||
out.write(")");
|
||||
}
|
||||
write!(out, "[{}]", constant);
|
||||
|
||||
last_was_pointer = false;
|
||||
}
|
||||
CDeclarator::Func(ref args, layout_vertical) => {
|
||||
if last_was_pointer {
|
||||
out.write(")");
|
||||
}
|
||||
|
||||
out.write("(");
|
||||
if args.is_empty() && config.language == Language::C {
|
||||
out.write("void");
|
||||
}
|
||||
if layout_vertical {
|
||||
let align_length = out.line_length_for_align();
|
||||
out.push_set_spaces(align_length);
|
||||
for (i, &(ref arg_ident, ref arg_ty)) in args.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(",");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
// Convert &Option<String> to Option<&str>
|
||||
let arg_ident = arg_ident.as_ref().map(|x| x.as_ref());
|
||||
|
||||
arg_ty.write(out, arg_ident, config);
|
||||
}
|
||||
out.pop_tab();
|
||||
} else {
|
||||
for (i, &(ref arg_ident, ref arg_ty)) in args.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(", ");
|
||||
}
|
||||
|
||||
// Convert &Option<String> to Option<&str>
|
||||
let arg_ident = arg_ident.as_ref().map(|x| x.as_ref());
|
||||
|
||||
arg_ty.write(out, arg_ident, config);
|
||||
}
|
||||
}
|
||||
out.write(")");
|
||||
|
||||
last_was_pointer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_func<F: Write>(
|
||||
out: &mut SourceWriter<F>,
|
||||
f: &Function,
|
||||
layout_vertical: bool,
|
||||
config: &Config,
|
||||
) {
|
||||
CDecl::from_func(f, layout_vertical, config).write(out, Some(f.path().name()), config);
|
||||
}
|
||||
|
||||
pub fn write_field<F: Write>(out: &mut SourceWriter<F>, t: &Type, ident: &str, config: &Config) {
|
||||
CDecl::from_type(t, config).write(out, Some(ident), config);
|
||||
}
|
||||
|
||||
pub fn write_type<F: Write>(out: &mut SourceWriter<F>, t: &Type, config: &Config) {
|
||||
CDecl::from_type(t, config).write(out, None, config);
|
||||
}
|
||||
1075
zeroidc/vendor/cbindgen/src/bindgen/config.rs
vendored
Normal file
1075
zeroidc/vendor/cbindgen/src/bindgen/config.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
57
zeroidc/vendor/cbindgen/src/bindgen/declarationtyperesolver.rs
vendored
Normal file
57
zeroidc/vendor/cbindgen/src/bindgen/declarationtyperesolver.rs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 crate::bindgen::ir::Path;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
|
||||
impl DeclarationType {
|
||||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
DeclarationType::Struct => "struct",
|
||||
DeclarationType::Enum => "enum",
|
||||
DeclarationType::Union => "union",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
|
||||
pub enum DeclarationType {
|
||||
Struct,
|
||||
Enum,
|
||||
Union,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DeclarationTypeResolver {
|
||||
types: HashMap<Path, Option<DeclarationType>>,
|
||||
}
|
||||
|
||||
impl DeclarationTypeResolver {
|
||||
fn insert(&mut self, path: &Path, ty: Option<DeclarationType>) {
|
||||
if let Entry::Vacant(vacant_entry) = self.types.entry(path.clone()) {
|
||||
vacant_entry.insert(ty);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_enum(&mut self, path: &Path) {
|
||||
self.insert(path, Some(DeclarationType::Enum));
|
||||
}
|
||||
|
||||
pub fn add_struct(&mut self, path: &Path) {
|
||||
self.insert(path, Some(DeclarationType::Struct));
|
||||
}
|
||||
|
||||
pub fn add_union(&mut self, path: &Path) {
|
||||
self.insert(path, Some(DeclarationType::Union));
|
||||
}
|
||||
|
||||
pub fn add_none(&mut self, path: &Path) {
|
||||
self.insert(path, None);
|
||||
}
|
||||
|
||||
pub fn type_for(&self, path: &Path) -> Option<DeclarationType> {
|
||||
*self.types.get(path)?
|
||||
}
|
||||
}
|
||||
48
zeroidc/vendor/cbindgen/src/bindgen/dependencies.rs
vendored
Normal file
48
zeroidc/vendor/cbindgen/src/bindgen/dependencies.rs
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::bindgen::ir::{ItemContainer, Path};
|
||||
|
||||
/// A dependency list is used for gathering what order to output the types.
|
||||
#[derive(Default)]
|
||||
pub struct Dependencies {
|
||||
pub order: Vec<ItemContainer>,
|
||||
pub items: HashSet<Path>,
|
||||
}
|
||||
|
||||
impl Dependencies {
|
||||
pub fn new() -> Dependencies {
|
||||
Dependencies {
|
||||
order: Vec::new(),
|
||||
items: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sort(&mut self) {
|
||||
// Sort untagged enums and opaque structs into their own layers because they don't
|
||||
// depend on each other or anything else.
|
||||
let ordering = |a: &ItemContainer, b: &ItemContainer| match (a, b) {
|
||||
(&ItemContainer::Enum(ref x), &ItemContainer::Enum(ref y))
|
||||
if x.tag.is_none() && y.tag.is_none() =>
|
||||
{
|
||||
x.path.cmp(&y.path)
|
||||
}
|
||||
(&ItemContainer::Enum(ref x), _) if x.tag.is_none() => Ordering::Less,
|
||||
(_, &ItemContainer::Enum(ref x)) if x.tag.is_none() => Ordering::Greater,
|
||||
|
||||
(&ItemContainer::OpaqueItem(ref x), &ItemContainer::OpaqueItem(ref y)) => {
|
||||
x.path.cmp(&y.path)
|
||||
}
|
||||
(&ItemContainer::OpaqueItem(_), _) => Ordering::Less,
|
||||
(_, &ItemContainer::OpaqueItem(_)) => Ordering::Greater,
|
||||
|
||||
_ => Ordering::Equal,
|
||||
};
|
||||
|
||||
self.order.sort_by(ordering);
|
||||
}
|
||||
}
|
||||
88
zeroidc/vendor/cbindgen/src/bindgen/error.rs
vendored
Normal file
88
zeroidc/vendor/cbindgen/src/bindgen/error.rs
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::error;
|
||||
use std::fmt;
|
||||
|
||||
pub use crate::bindgen::cargo::cargo_expand::Error as CargoExpandError;
|
||||
pub use crate::bindgen::cargo::cargo_metadata::Error as CargoMetadataError;
|
||||
pub use crate::bindgen::cargo::cargo_toml::Error as CargoTomlError;
|
||||
pub use syn::parse::Error as ParseError;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum Error {
|
||||
CargoMetadata(String, CargoMetadataError),
|
||||
CargoToml(String, CargoTomlError),
|
||||
CargoExpand(String, CargoExpandError),
|
||||
ParseSyntaxError {
|
||||
crate_name: String,
|
||||
src_path: String,
|
||||
error: ParseError,
|
||||
},
|
||||
ParseCannotOpenFile {
|
||||
crate_name: String,
|
||||
src_path: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Error::CargoMetadata(ref path, ref error) => write!(
|
||||
f,
|
||||
"Couldn't execute `cargo metadata` with manifest {:?}: {:?}",
|
||||
path, error
|
||||
),
|
||||
Error::CargoToml(ref path, ref error) => {
|
||||
write!(f, "Couldn't load manifest file {:?}: {:?}", path, error)
|
||||
}
|
||||
Error::CargoExpand(ref crate_name, ref error) => write!(
|
||||
f,
|
||||
"Parsing crate `{}`: couldn't run `cargo rustc -Zunpretty=expanded`: {:?}",
|
||||
crate_name, error
|
||||
),
|
||||
Error::ParseSyntaxError {
|
||||
ref crate_name,
|
||||
ref src_path,
|
||||
ref error,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"Parsing crate `{}`:`{}`:\n{:?}",
|
||||
crate_name, src_path, error
|
||||
)?;
|
||||
|
||||
if !src_path.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
"\nTry running `rustc -Z parse-only {}` to see a nicer error message",
|
||||
src_path,
|
||||
)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Error::ParseCannotOpenFile {
|
||||
ref crate_name,
|
||||
ref src_path,
|
||||
} => write!(
|
||||
f,
|
||||
"Parsing crate `{}`: cannot open file `{}`.",
|
||||
crate_name, src_path
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Error::CargoMetadata(_, ref error) => Some(error),
|
||||
Error::CargoToml(_, ref error) => Some(error),
|
||||
Error::CargoExpand(_, ref error) => Some(error),
|
||||
Error::ParseSyntaxError { ref error, .. } => Some(error),
|
||||
Error::ParseCannotOpenFile { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
179
zeroidc/vendor/cbindgen/src/bindgen/ir/annotation.rs
vendored
Normal file
179
zeroidc/vendor/cbindgen/src/bindgen/ir/annotation.rs
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::utilities::SynAttributeHelpers;
|
||||
|
||||
// A system for specifying properties on items. Annotations are
|
||||
// given through document comments and parsed by this code.
|
||||
//
|
||||
// An annotation is in the form cbindgen:PROPERTY=VALUE
|
||||
// Where PROPERTY depends on the item
|
||||
// Where VALUE can be
|
||||
// * list - [Item1, Item2, Item3, ...]
|
||||
// * atom - Foo
|
||||
// * bool - true,false
|
||||
// Examples:
|
||||
// * cbindgen:field-names=[mHandle, mNamespace]
|
||||
// * cbindgen:function-postfix=WR_DESTRUCTOR_SAFE
|
||||
|
||||
/// A value specified by an annotation.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum AnnotationValue {
|
||||
List(Vec<String>),
|
||||
Atom(Option<String>),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
/// A set of annotations specified by a document comment.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct AnnotationSet {
|
||||
annotations: HashMap<String, AnnotationValue>,
|
||||
pub must_use: bool,
|
||||
}
|
||||
|
||||
impl AnnotationSet {
|
||||
pub fn new() -> AnnotationSet {
|
||||
AnnotationSet {
|
||||
annotations: HashMap::new(),
|
||||
must_use: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.annotations.is_empty() && !self.must_use
|
||||
}
|
||||
|
||||
pub(crate) fn must_use(&self, config: &Config) -> bool {
|
||||
self.must_use && config.language != Language::Cython
|
||||
}
|
||||
|
||||
pub fn load(attrs: &[syn::Attribute]) -> Result<AnnotationSet, String> {
|
||||
let lines = attrs.get_comment_lines();
|
||||
let lines: Vec<&str> = lines
|
||||
.iter()
|
||||
.filter_map(|line| {
|
||||
let line = line.trim_start();
|
||||
if !line.starts_with("cbindgen:") {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(line)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let must_use = attrs.has_attr_word("must_use");
|
||||
|
||||
let mut annotations = HashMap::new();
|
||||
|
||||
// Look at each line for an annotation
|
||||
for line in lines {
|
||||
debug_assert!(line.starts_with("cbindgen:"));
|
||||
|
||||
// Remove the "cbindgen:" prefix
|
||||
let annotation = &line[9..];
|
||||
|
||||
// Split the annotation in two
|
||||
let parts: Vec<&str> = annotation.split('=').map(|x| x.trim()).collect();
|
||||
|
||||
if parts.len() > 2 {
|
||||
return Err(format!("Couldn't parse {}.", line));
|
||||
}
|
||||
|
||||
// Grab the name that this annotation is modifying
|
||||
let name = parts[0];
|
||||
|
||||
// If the annotation only has a name, assume it's setting a bool flag
|
||||
if parts.len() == 1 {
|
||||
annotations.insert(name.to_string(), AnnotationValue::Bool(true));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse the value we're setting the name to
|
||||
let value = parts[1];
|
||||
|
||||
if let Some(x) = parse_list(value) {
|
||||
annotations.insert(name.to_string(), AnnotationValue::List(x));
|
||||
continue;
|
||||
}
|
||||
if let Ok(x) = value.parse::<bool>() {
|
||||
annotations.insert(name.to_string(), AnnotationValue::Bool(x));
|
||||
continue;
|
||||
}
|
||||
annotations.insert(
|
||||
name.to_string(),
|
||||
if value.is_empty() {
|
||||
AnnotationValue::Atom(None)
|
||||
} else {
|
||||
AnnotationValue::Atom(Some(value.to_string()))
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Ok(AnnotationSet {
|
||||
annotations,
|
||||
must_use,
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds an annotation value if none is specified.
|
||||
pub fn add_default(&mut self, name: &str, value: AnnotationValue) {
|
||||
if let Entry::Vacant(e) = self.annotations.entry(name.to_string()) {
|
||||
e.insert(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list(&self, name: &str) -> Option<Vec<String>> {
|
||||
match self.annotations.get(name) {
|
||||
Some(&AnnotationValue::List(ref x)) => Some(x.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn atom(&self, name: &str) -> Option<Option<String>> {
|
||||
match self.annotations.get(name) {
|
||||
Some(&AnnotationValue::Atom(ref x)) => Some(x.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn bool(&self, name: &str) -> Option<bool> {
|
||||
match self.annotations.get(name) {
|
||||
Some(&AnnotationValue::Bool(ref x)) => Some(*x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_atom<T>(&self, name: &str) -> Option<T>
|
||||
where
|
||||
T: Default + FromStr,
|
||||
{
|
||||
match self.annotations.get(name) {
|
||||
Some(&AnnotationValue::Atom(ref x)) => Some(
|
||||
x.as_ref()
|
||||
.map_or(T::default(), |y| y.parse::<T>().ok().unwrap()),
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse lists like "[x, y, z]". This is not implemented efficiently or well.
|
||||
fn parse_list(list: &str) -> Option<Vec<String>> {
|
||||
if list.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
match (list.chars().next(), list.chars().last()) {
|
||||
(Some('['), Some(']')) => Some(
|
||||
list[1..list.len() - 1]
|
||||
.split(',')
|
||||
.map(|x| x.trim().to_string())
|
||||
.collect(),
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
365
zeroidc/vendor/cbindgen/src/bindgen/ir/cfg.rs
vendored
Normal file
365
zeroidc/vendor/cbindgen/src/bindgen/ir/cfg.rs
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::fmt;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::cargo::cargo_metadata::Dependency;
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::writer::SourceWriter;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum DefineKey<'a> {
|
||||
Boolean(&'a str),
|
||||
Named(&'a str, &'a str),
|
||||
}
|
||||
|
||||
impl<'a> DefineKey<'a> {
|
||||
fn load(key: &str) -> DefineKey {
|
||||
// TODO: dirty parser
|
||||
if !key.contains('=') {
|
||||
return DefineKey::Boolean(key);
|
||||
}
|
||||
|
||||
let mut splits = key.trim().split('=');
|
||||
|
||||
let name = match splits.next() {
|
||||
Some(n) => n.trim(),
|
||||
None => return DefineKey::Boolean(key),
|
||||
};
|
||||
|
||||
let value = match splits.next() {
|
||||
Some(v) => v.trim(),
|
||||
None => return DefineKey::Boolean(key),
|
||||
};
|
||||
|
||||
if splits.next().is_some() {
|
||||
return DefineKey::Boolean(key);
|
||||
}
|
||||
|
||||
DefineKey::Named(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Cfg {
|
||||
Boolean(String),
|
||||
Named(String, String),
|
||||
Any(Vec<Cfg>),
|
||||
All(Vec<Cfg>),
|
||||
Not(Box<Cfg>),
|
||||
}
|
||||
|
||||
impl fmt::Display for Cfg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Cfg::Boolean(key) => write!(f, "{}", key),
|
||||
Cfg::Named(key, value) => write!(f, "{} = {:?}", key, value),
|
||||
Cfg::Any(cfgs) => {
|
||||
write!(f, "any(")?;
|
||||
for (index, cfg) in cfgs.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", cfg)?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Cfg::All(cfgs) => {
|
||||
write!(f, "all(")?;
|
||||
for (index, cfg) in cfgs.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", cfg)?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Cfg::Not(cfg) => write!(f, "not({})", cfg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Cfg {
|
||||
pub fn join(cfgs: &[Cfg]) -> Option<Cfg> {
|
||||
if cfgs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Cfg::All(cfgs.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append(parent: Option<&Cfg>, child: Option<Cfg>) -> Option<Cfg> {
|
||||
match (parent, child) {
|
||||
(None, None) => None,
|
||||
(None, Some(child)) => Some(child),
|
||||
(Some(parent), None) => Some(parent.clone()),
|
||||
(Some(parent), Some(child)) => Some(Cfg::All(vec![parent.clone(), child])),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(attrs: &[syn::Attribute]) -> Option<Cfg> {
|
||||
let mut configs = Vec::new();
|
||||
|
||||
for attr in attrs {
|
||||
if let Ok(syn::Meta::List(syn::MetaList { path, nested, .. })) = attr.parse_meta() {
|
||||
if !path.is_ident("cfg") || nested.len() != 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(config) = Cfg::load_single(nested.first().unwrap()) {
|
||||
configs.push(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match configs.len() {
|
||||
0 => None,
|
||||
1 => Some(configs.pop().unwrap()),
|
||||
_ => Some(Cfg::All(configs)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_metadata(dependency: &Dependency) -> Option<Cfg> {
|
||||
let target = dependency.target.as_ref()?;
|
||||
match syn::parse_str::<syn::Meta>(target) {
|
||||
Ok(target) => {
|
||||
// Parsing succeeded using the #[cfg] syntax
|
||||
if let syn::Meta::List(syn::MetaList { path, nested, .. }) = target {
|
||||
if !path.is_ident("cfg") || nested.len() != 1 {
|
||||
return None;
|
||||
}
|
||||
Cfg::load_single(nested.first().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Parsing failed using #[cfg], this may be a literal target
|
||||
// name
|
||||
Cfg::load_single(&syn::NestedMeta::Lit(syn::Lit::Str(syn::LitStr::new(
|
||||
target,
|
||||
proc_macro2::Span::call_site(),
|
||||
))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_single(item: &syn::NestedMeta) -> Option<Cfg> {
|
||||
Some(match *item {
|
||||
syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => {
|
||||
Cfg::Boolean(format!("{}", path.segments.first().unwrap().ident))
|
||||
}
|
||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
ref path,
|
||||
lit: syn::Lit::Str(ref value),
|
||||
..
|
||||
})) => Cfg::Named(
|
||||
format!("{}", path.segments.first().unwrap().ident),
|
||||
value.value(),
|
||||
),
|
||||
syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList {
|
||||
ref path,
|
||||
ref nested,
|
||||
..
|
||||
})) => {
|
||||
if path.is_ident("any") {
|
||||
Cfg::Any(Cfg::load_list(nested.iter())?)
|
||||
} else if path.is_ident("all") {
|
||||
Cfg::All(Cfg::load_list(nested.iter())?)
|
||||
} else if path.is_ident("not") {
|
||||
if nested.len() != 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Cfg::Not(Box::new(Cfg::load_single(&nested[0])?))
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn load_list<'a, I: Iterator<Item = &'a syn::NestedMeta>>(attrs: I) -> Option<Vec<Cfg>> {
|
||||
let mut configs = Vec::new();
|
||||
|
||||
for attr in attrs {
|
||||
configs.push(Cfg::load_single(attr)?);
|
||||
}
|
||||
|
||||
if configs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(configs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToCondition: Sized {
|
||||
fn to_condition(&self, config: &Config) -> Option<Condition>;
|
||||
}
|
||||
|
||||
impl<'a> ToCondition for Option<Cfg> {
|
||||
fn to_condition(&self, config: &Config) -> Option<Condition> {
|
||||
self.as_ref()?.to_condition(config)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToCondition for Cfg {
|
||||
fn to_condition(&self, config: &Config) -> Option<Condition> {
|
||||
match *self {
|
||||
Cfg::Boolean(ref cfg_name) => {
|
||||
let define = config
|
||||
.defines
|
||||
.iter()
|
||||
.find(|(key, ..)| DefineKey::Boolean(cfg_name) == DefineKey::load(key));
|
||||
if let Some((_, define)) = define {
|
||||
Some(Condition::Define(define.to_owned()))
|
||||
} else {
|
||||
warn!(
|
||||
"Missing `[defines]` entry for `{}` in cbindgen config.",
|
||||
self,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
Cfg::Named(ref cfg_name, ref cfg_value) => {
|
||||
let define = config.defines.iter().find(|(key, ..)| {
|
||||
DefineKey::Named(cfg_name, cfg_value) == DefineKey::load(key)
|
||||
});
|
||||
if let Some((_, define)) = define {
|
||||
Some(Condition::Define(define.to_owned()))
|
||||
} else {
|
||||
warn!(
|
||||
"Missing `[defines]` entry for `{}` in cbindgen config.",
|
||||
self,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
Cfg::Any(ref children) => {
|
||||
let conditions: Vec<_> = children
|
||||
.iter()
|
||||
.filter_map(|x| x.to_condition(config))
|
||||
.collect();
|
||||
match conditions.len() {
|
||||
0 => None,
|
||||
1 => conditions.into_iter().next(),
|
||||
_ => Some(Condition::Any(conditions)),
|
||||
}
|
||||
}
|
||||
Cfg::All(ref children) => {
|
||||
let cfgs: Vec<_> = children
|
||||
.iter()
|
||||
.filter_map(|x| x.to_condition(config))
|
||||
.collect();
|
||||
match cfgs.len() {
|
||||
0 => None,
|
||||
1 => cfgs.into_iter().next(),
|
||||
_ => Some(Condition::All(cfgs)),
|
||||
}
|
||||
}
|
||||
Cfg::Not(ref child) => child
|
||||
.to_condition(config)
|
||||
.map(|cfg| Condition::Not(Box::new(cfg))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Condition {
|
||||
Define(String),
|
||||
Any(Vec<Condition>),
|
||||
All(Vec<Condition>),
|
||||
Not(Box<Condition>),
|
||||
}
|
||||
|
||||
impl Condition {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
match *self {
|
||||
Condition::Define(ref define) => {
|
||||
if config.language == Language::Cython {
|
||||
write!(out, "{}", define);
|
||||
} else {
|
||||
out.write("defined(");
|
||||
write!(out, "{}", define);
|
||||
out.write(")");
|
||||
}
|
||||
}
|
||||
Condition::Any(ref conditions) => {
|
||||
out.write("(");
|
||||
for (i, condition) in conditions.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(if config.language == Language::Cython {
|
||||
" or "
|
||||
} else {
|
||||
" || "
|
||||
});
|
||||
}
|
||||
condition.write(config, out);
|
||||
}
|
||||
out.write(")");
|
||||
}
|
||||
Condition::All(ref conditions) => {
|
||||
out.write("(");
|
||||
for (i, condition) in conditions.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(if config.language == Language::Cython {
|
||||
" and "
|
||||
} else {
|
||||
" && "
|
||||
});
|
||||
}
|
||||
condition.write(config, out);
|
||||
}
|
||||
out.write(")");
|
||||
}
|
||||
Condition::Not(ref condition) => {
|
||||
out.write(if config.language == Language::Cython {
|
||||
"not "
|
||||
} else {
|
||||
"!"
|
||||
});
|
||||
condition.write(config, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ConditionWrite {
|
||||
fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
|
||||
fn write_after<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
|
||||
}
|
||||
|
||||
impl ConditionWrite for Option<Condition> {
|
||||
fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
if let Some(ref cfg) = *self {
|
||||
if config.language == Language::Cython {
|
||||
out.write("IF ");
|
||||
cfg.write(config, out);
|
||||
out.open_brace();
|
||||
} else {
|
||||
out.push_set_spaces(0);
|
||||
out.write("#if ");
|
||||
cfg.write(config, out);
|
||||
out.pop_set_spaces();
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_after<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
if self.is_some() {
|
||||
if config.language == Language::Cython {
|
||||
out.close_brace(false);
|
||||
} else {
|
||||
out.new_line();
|
||||
out.push_set_spaces(0);
|
||||
out.write("#endif");
|
||||
out.pop_set_spaces();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
603
zeroidc/vendor/cbindgen/src/bindgen/ir/constant.rs
vendored
Normal file
603
zeroidc/vendor/cbindgen/src/bindgen/ir/constant.rs
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
use syn::{self, UnOp};
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
|
||||
Struct, ToCondition, Type,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
use crate::bindgen::Bindings;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Literal {
|
||||
Expr(String),
|
||||
Path(String),
|
||||
PostfixUnaryOp {
|
||||
op: &'static str,
|
||||
value: Box<Literal>,
|
||||
},
|
||||
BinOp {
|
||||
left: Box<Literal>,
|
||||
op: &'static str,
|
||||
right: Box<Literal>,
|
||||
},
|
||||
Struct {
|
||||
path: Path,
|
||||
export_name: String,
|
||||
fields: HashMap<String, Literal>,
|
||||
},
|
||||
Cast {
|
||||
ty: Type,
|
||||
value: Box<Literal>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
fn replace_self_with(&mut self, self_ty: &Path) {
|
||||
match *self {
|
||||
Literal::PostfixUnaryOp { ref mut value, .. } => {
|
||||
value.replace_self_with(self_ty);
|
||||
}
|
||||
Literal::BinOp {
|
||||
ref mut left,
|
||||
ref mut right,
|
||||
..
|
||||
} => {
|
||||
left.replace_self_with(self_ty);
|
||||
right.replace_self_with(self_ty);
|
||||
}
|
||||
Literal::Struct {
|
||||
ref mut path,
|
||||
ref mut export_name,
|
||||
ref mut fields,
|
||||
} => {
|
||||
if path.replace_self_with(self_ty) {
|
||||
*export_name = self_ty.name().to_owned();
|
||||
}
|
||||
for ref mut expr in fields.values_mut() {
|
||||
expr.replace_self_with(self_ty);
|
||||
}
|
||||
}
|
||||
Literal::Cast {
|
||||
ref mut ty,
|
||||
ref mut value,
|
||||
} => {
|
||||
ty.replace_self_with(self_ty);
|
||||
value.replace_self_with(self_ty);
|
||||
}
|
||||
Literal::Expr(..) | Literal::Path(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid(&self, bindings: &Bindings) -> bool {
|
||||
match *self {
|
||||
Literal::Expr(..) => true,
|
||||
Literal::Path(..) => true,
|
||||
Literal::PostfixUnaryOp { ref value, .. } => value.is_valid(bindings),
|
||||
Literal::BinOp {
|
||||
ref left,
|
||||
ref right,
|
||||
..
|
||||
} => left.is_valid(bindings) && right.is_valid(bindings),
|
||||
Literal::Struct { ref path, .. } => bindings.struct_exists(path),
|
||||
Literal::Cast { ref value, .. } => value.is_valid(bindings),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uses_only_primitive_types(&self) -> bool {
|
||||
match self {
|
||||
Literal::Expr(..) => true,
|
||||
Literal::Path(..) => true,
|
||||
Literal::PostfixUnaryOp { ref value, .. } => value.uses_only_primitive_types(),
|
||||
Literal::BinOp {
|
||||
ref left,
|
||||
ref right,
|
||||
..
|
||||
} => left.uses_only_primitive_types() & right.uses_only_primitive_types(),
|
||||
Literal::Struct { .. } => false,
|
||||
Literal::Cast { ref value, ref ty } => {
|
||||
value.uses_only_primitive_types() && ty.is_primitive_or_ptr_primitive()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
pub fn rename_for_config(&mut self, config: &Config) {
|
||||
match self {
|
||||
Literal::Struct {
|
||||
ref mut export_name,
|
||||
fields,
|
||||
..
|
||||
} => {
|
||||
config.export.rename(export_name);
|
||||
for lit in fields.values_mut() {
|
||||
lit.rename_for_config(config);
|
||||
}
|
||||
}
|
||||
Literal::Path(ref mut name) => {
|
||||
config.export.rename(name);
|
||||
}
|
||||
Literal::PostfixUnaryOp { ref mut value, .. } => {
|
||||
value.rename_for_config(config);
|
||||
}
|
||||
Literal::BinOp {
|
||||
ref mut left,
|
||||
ref mut right,
|
||||
..
|
||||
} => {
|
||||
left.rename_for_config(config);
|
||||
right.rename_for_config(config);
|
||||
}
|
||||
Literal::Expr(_) => {}
|
||||
Literal::Cast {
|
||||
ref mut ty,
|
||||
ref mut value,
|
||||
} => {
|
||||
ty.rename_for_config(config, &GenericParams::default());
|
||||
value.rename_for_config(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Translate from full blown `syn::Expr` into a simpler `Literal` type
|
||||
pub fn load(expr: &syn::Expr) -> Result<Literal, String> {
|
||||
match *expr {
|
||||
// Match binary expressions of the form `a * b`
|
||||
syn::Expr::Binary(ref bin_expr) => {
|
||||
let l = Self::load(&bin_expr.left)?;
|
||||
let r = Self::load(&bin_expr.right)?;
|
||||
let op = match bin_expr.op {
|
||||
syn::BinOp::Add(..) => "+",
|
||||
syn::BinOp::Sub(..) => "-",
|
||||
syn::BinOp::Mul(..) => "*",
|
||||
syn::BinOp::Div(..) => "/",
|
||||
syn::BinOp::Rem(..) => "%",
|
||||
syn::BinOp::And(..) => "&&",
|
||||
syn::BinOp::Or(..) => "||",
|
||||
syn::BinOp::BitXor(..) => "^",
|
||||
syn::BinOp::BitAnd(..) => "&",
|
||||
syn::BinOp::BitOr(..) => "|",
|
||||
syn::BinOp::Shl(..) => "<<",
|
||||
syn::BinOp::Shr(..) => ">>",
|
||||
syn::BinOp::Eq(..) => "==",
|
||||
syn::BinOp::Lt(..) => "<",
|
||||
syn::BinOp::Le(..) => "<=",
|
||||
syn::BinOp::Ne(..) => "!=",
|
||||
syn::BinOp::Ge(..) => ">=",
|
||||
syn::BinOp::Gt(..) => ">",
|
||||
syn::BinOp::AddEq(..) => "+=",
|
||||
syn::BinOp::SubEq(..) => "-=",
|
||||
syn::BinOp::MulEq(..) => "*=",
|
||||
syn::BinOp::DivEq(..) => "/=",
|
||||
syn::BinOp::RemEq(..) => "%=",
|
||||
syn::BinOp::BitXorEq(..) => "^=",
|
||||
syn::BinOp::BitAndEq(..) => "&=",
|
||||
syn::BinOp::BitOrEq(..) => "|=",
|
||||
syn::BinOp::ShlEq(..) => ">>=",
|
||||
syn::BinOp::ShrEq(..) => "<<=",
|
||||
};
|
||||
Ok(Literal::BinOp {
|
||||
left: Box::new(l),
|
||||
op,
|
||||
right: Box::new(r),
|
||||
})
|
||||
}
|
||||
|
||||
// Match literals like true, 'a', 32 etc
|
||||
syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => {
|
||||
match lit {
|
||||
syn::Lit::Byte(ref value) => Ok(Literal::Expr(format!("{}", value.value()))),
|
||||
syn::Lit::Char(ref value) => Ok(Literal::Expr(match value.value() as u32 {
|
||||
0..=255 => format!("'{}'", value.value().escape_default()),
|
||||
other_code => format!(r"U'\U{:08X}'", other_code),
|
||||
})),
|
||||
syn::Lit::Int(ref value) => {
|
||||
if value.base10_parse::<i64>().is_err() {
|
||||
Ok(Literal::Expr(format!("{}ULL", value.base10_digits())))
|
||||
} else {
|
||||
Ok(Literal::Expr(value.base10_digits().to_string()))
|
||||
}
|
||||
}
|
||||
syn::Lit::Float(ref value) => {
|
||||
Ok(Literal::Expr(value.base10_digits().to_string()))
|
||||
}
|
||||
syn::Lit::Bool(ref value) => Ok(Literal::Expr(format!("{}", value.value))),
|
||||
// TODO: Add support for byte string and Verbatim
|
||||
_ => Err(format!("Unsupported literal expression. {:?}", *lit)),
|
||||
}
|
||||
}
|
||||
|
||||
syn::Expr::Struct(syn::ExprStruct {
|
||||
ref path,
|
||||
ref fields,
|
||||
..
|
||||
}) => {
|
||||
let struct_name = path.segments[0].ident.to_string();
|
||||
let mut field_map = HashMap::<String, Literal>::default();
|
||||
for field in fields {
|
||||
let ident = match field.member {
|
||||
syn::Member::Named(ref name) => name.to_string(),
|
||||
syn::Member::Unnamed(ref index) => format!("_{}", index.index),
|
||||
};
|
||||
let key = ident.to_string();
|
||||
let value = Literal::load(&field.expr)?;
|
||||
field_map.insert(key, value);
|
||||
}
|
||||
Ok(Literal::Struct {
|
||||
path: Path::new(struct_name.clone()),
|
||||
export_name: struct_name,
|
||||
fields: field_map,
|
||||
})
|
||||
}
|
||||
|
||||
syn::Expr::Unary(syn::ExprUnary {
|
||||
ref op, ref expr, ..
|
||||
}) => match *op {
|
||||
UnOp::Neg(_) => {
|
||||
let val = Self::load(expr)?;
|
||||
Ok(Literal::PostfixUnaryOp {
|
||||
op: "-",
|
||||
value: Box::new(val),
|
||||
})
|
||||
}
|
||||
_ => Err(format!("Unsupported Unary expression. {:?}", *op)),
|
||||
},
|
||||
|
||||
// Match identifiers, like `5 << SHIFT`
|
||||
syn::Expr::Path(syn::ExprPath {
|
||||
path: syn::Path { ref segments, .. },
|
||||
..
|
||||
}) => {
|
||||
// Handle only the simplest identifiers and error for anything else.
|
||||
if segments.len() == 1 {
|
||||
Ok(Literal::Path(format!("{}", segments.last().unwrap().ident)))
|
||||
} else {
|
||||
Err(format!("Unsupported path expression. {:?}", *segments))
|
||||
}
|
||||
}
|
||||
|
||||
syn::Expr::Paren(syn::ExprParen { ref expr, .. }) => Self::load(expr),
|
||||
|
||||
syn::Expr::Cast(syn::ExprCast {
|
||||
ref expr, ref ty, ..
|
||||
}) => {
|
||||
let val = Self::load(expr)?;
|
||||
match Type::load(ty)? {
|
||||
Some(ty) => Ok(Literal::Cast {
|
||||
ty,
|
||||
value: Box::new(val),
|
||||
}),
|
||||
None => Err("Cannot cast to zero sized type.".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(format!("Unsupported expression. {:?}", *expr)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
match self {
|
||||
Literal::Expr(v) => match (&**v, config.language) {
|
||||
("true", Language::Cython) => write!(out, "True"),
|
||||
("false", Language::Cython) => write!(out, "False"),
|
||||
(v, _) => write!(out, "{}", v),
|
||||
},
|
||||
Literal::Path(v) => write!(out, "{}", v),
|
||||
Literal::PostfixUnaryOp { op, ref value } => {
|
||||
write!(out, "{}", op);
|
||||
value.write(config, out);
|
||||
}
|
||||
Literal::BinOp {
|
||||
ref left,
|
||||
op,
|
||||
ref right,
|
||||
} => {
|
||||
write!(out, "(");
|
||||
left.write(config, out);
|
||||
write!(out, " {} ", op);
|
||||
right.write(config, out);
|
||||
write!(out, ")");
|
||||
}
|
||||
Literal::Cast { ref ty, ref value } => {
|
||||
out.write(if config.language == Language::Cython {
|
||||
"<"
|
||||
} else {
|
||||
"("
|
||||
});
|
||||
ty.write(config, out);
|
||||
out.write(if config.language == Language::Cython {
|
||||
">"
|
||||
} else {
|
||||
")"
|
||||
});
|
||||
value.write(config, out);
|
||||
}
|
||||
Literal::Struct {
|
||||
export_name,
|
||||
fields,
|
||||
path,
|
||||
} => {
|
||||
match config.language {
|
||||
Language::C => write!(out, "({})", export_name),
|
||||
Language::Cxx => write!(out, "{}", export_name),
|
||||
Language::Cython => write!(out, "<{}>", export_name),
|
||||
}
|
||||
|
||||
write!(out, "{{ ");
|
||||
let mut is_first_field = true;
|
||||
// In C++, same order as defined is required.
|
||||
let ordered_fields = out.bindings().struct_field_names(path);
|
||||
for ordered_key in ordered_fields.iter() {
|
||||
if let Some(lit) = fields.get(ordered_key) {
|
||||
if !is_first_field {
|
||||
write!(out, ", ");
|
||||
} else {
|
||||
is_first_field = false;
|
||||
}
|
||||
match config.language {
|
||||
Language::Cxx => write!(out, "/* .{} = */ ", ordered_key),
|
||||
Language::C => write!(out, ".{} = ", ordered_key),
|
||||
Language::Cython => {}
|
||||
}
|
||||
lit.write(config, out);
|
||||
}
|
||||
}
|
||||
write!(out, " }}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Constant {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub ty: Type,
|
||||
pub value: Literal,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
pub associated_to: Option<Path>,
|
||||
}
|
||||
|
||||
impl Constant {
|
||||
pub fn load(
|
||||
path: Path,
|
||||
mod_cfg: Option<&Cfg>,
|
||||
ty: &syn::Type,
|
||||
expr: &syn::Expr,
|
||||
attrs: &[syn::Attribute],
|
||||
associated_to: Option<Path>,
|
||||
) -> Result<Constant, String> {
|
||||
let ty = Type::load(ty)?;
|
||||
let mut ty = match ty {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
return Err("Cannot have a zero sized const definition.".to_owned());
|
||||
}
|
||||
};
|
||||
|
||||
let mut lit = Literal::load(expr)?;
|
||||
|
||||
if let Some(ref associated_to) = associated_to {
|
||||
ty.replace_self_with(associated_to);
|
||||
lit.replace_self_with(associated_to);
|
||||
}
|
||||
|
||||
Ok(Constant::new(
|
||||
path,
|
||||
ty,
|
||||
lit,
|
||||
Cfg::append(mod_cfg, Cfg::load(attrs)),
|
||||
AnnotationSet::load(attrs)?,
|
||||
Documentation::load(attrs),
|
||||
associated_to,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
path: Path,
|
||||
ty: Type,
|
||||
value: Literal,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
associated_to: Option<Path>,
|
||||
) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
ty,
|
||||
value,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
associated_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uses_only_primitive_types(&self) -> bool {
|
||||
self.value.uses_only_primitive_types() && self.ty.is_primitive_or_ptr_primitive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Constant {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.ty.add_dependencies(library, out);
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Constant(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
if self.associated_to.is_none() {
|
||||
config.export.rename(&mut self.export_name);
|
||||
}
|
||||
self.value.rename_for_config(config);
|
||||
self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
impl Constant {
|
||||
pub fn write_declaration<F: Write>(
|
||||
&self,
|
||||
config: &Config,
|
||||
out: &mut SourceWriter<F>,
|
||||
associated_to_struct: &Struct,
|
||||
) {
|
||||
debug_assert!(self.associated_to.is_some());
|
||||
debug_assert!(config.language == Language::Cxx);
|
||||
debug_assert!(!associated_to_struct.is_transparent);
|
||||
debug_assert!(config.structure.associated_constants_in_body);
|
||||
debug_assert!(config.constant.allow_static_const);
|
||||
|
||||
if let Type::Ptr { is_const: true, .. } = self.ty {
|
||||
out.write("static ");
|
||||
} else {
|
||||
out.write("static const ");
|
||||
}
|
||||
self.ty.write(config, out);
|
||||
write!(out, " {};", self.export_name())
|
||||
}
|
||||
|
||||
pub fn write<F: Write>(
|
||||
&self,
|
||||
config: &Config,
|
||||
out: &mut SourceWriter<F>,
|
||||
associated_to_struct: Option<&Struct>,
|
||||
) {
|
||||
if let Some(assoc) = associated_to_struct {
|
||||
if assoc.is_generic() {
|
||||
return; // Not tested / implemented yet, so bail out.
|
||||
}
|
||||
}
|
||||
|
||||
if !self.value.is_valid(out.bindings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let associated_to_transparent = associated_to_struct.map_or(false, |s| s.is_transparent);
|
||||
|
||||
let in_body = associated_to_struct.is_some()
|
||||
&& config.language == Language::Cxx
|
||||
&& config.structure.associated_constants_in_body
|
||||
&& config.constant.allow_static_const
|
||||
&& !associated_to_transparent;
|
||||
|
||||
let condition = self.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
let name = if in_body {
|
||||
Cow::Owned(format!(
|
||||
"{}::{}",
|
||||
associated_to_struct.unwrap().export_name(),
|
||||
self.export_name(),
|
||||
))
|
||||
} else if self.associated_to.is_none() {
|
||||
Cow::Borrowed(self.export_name())
|
||||
} else {
|
||||
let associated_name = match associated_to_struct {
|
||||
Some(s) => Cow::Borrowed(s.export_name()),
|
||||
None => {
|
||||
let mut name = self.associated_to.as_ref().unwrap().name().to_owned();
|
||||
config.export.rename(&mut name);
|
||||
Cow::Owned(name)
|
||||
}
|
||||
};
|
||||
|
||||
Cow::Owned(format!("{}_{}", associated_name, self.export_name()))
|
||||
};
|
||||
|
||||
let value = match self.value {
|
||||
Literal::Struct {
|
||||
ref fields,
|
||||
ref path,
|
||||
..
|
||||
} if out.bindings().struct_is_transparent(path) => fields.iter().next().unwrap().1,
|
||||
_ => &self.value,
|
||||
};
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
let allow_constexpr = if let Type::Primitive(..) = self.ty {
|
||||
config.constant.allow_constexpr
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
match config.language {
|
||||
Language::Cxx if config.constant.allow_static_const || allow_constexpr => {
|
||||
if allow_constexpr {
|
||||
out.write("constexpr ")
|
||||
}
|
||||
|
||||
if config.constant.allow_static_const {
|
||||
out.write(if in_body { "inline " } else { "static " });
|
||||
}
|
||||
|
||||
if let Type::Ptr { is_const: true, .. } = self.ty {
|
||||
// Nothing.
|
||||
} else {
|
||||
out.write("const ");
|
||||
}
|
||||
|
||||
self.ty.write(config, out);
|
||||
write!(out, " {} = ", name);
|
||||
value.write(config, out);
|
||||
write!(out, ";");
|
||||
}
|
||||
Language::Cxx | Language::C => {
|
||||
write!(out, "#define {} ", name);
|
||||
value.write(config, out);
|
||||
}
|
||||
Language::Cython => {
|
||||
out.write("const ");
|
||||
self.ty.write(config, out);
|
||||
// For extern Cython declarations the initializer is ignored,
|
||||
// but still useful as documentation, so we write it as a comment.
|
||||
write!(out, " {} # = ", name);
|
||||
value.write(config, out);
|
||||
}
|
||||
}
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
}
|
||||
106
zeroidc/vendor/cbindgen/src/bindgen/ir/documentation.rs
vendored
Normal file
106
zeroidc/vendor/cbindgen/src/bindgen/ir/documentation.rs
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Config, DocumentationStyle, Language};
|
||||
use crate::bindgen::utilities::SynAttributeHelpers;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Documentation {
|
||||
pub doc_comment: Vec<String>,
|
||||
}
|
||||
|
||||
impl Documentation {
|
||||
pub fn load(attrs: &[syn::Attribute]) -> Self {
|
||||
let doc = attrs
|
||||
.get_comment_lines()
|
||||
.into_iter()
|
||||
.filter(|x| !x.trim_start().starts_with("cbindgen:"))
|
||||
.collect();
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Documentation {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
if self.doc_comment.is_empty() || !config.documentation {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cython uses Python-style comments, so `documentation_style` is not relevant.
|
||||
if config.language == Language::Cython {
|
||||
for line in &self.doc_comment {
|
||||
write!(out, "#{}", line);
|
||||
out.new_line();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let style = match config.documentation_style {
|
||||
DocumentationStyle::Auto if config.language == Language::C => DocumentationStyle::Doxy,
|
||||
DocumentationStyle::Auto if config.language == Language::Cxx => DocumentationStyle::Cxx,
|
||||
DocumentationStyle::Auto => DocumentationStyle::C, // Fallback if `Language` gets extended.
|
||||
other => other,
|
||||
};
|
||||
|
||||
// Following these documents for style conventions:
|
||||
// https://en.wikibooks.org/wiki/C++_Programming/Code/Style_Conventions/Comments
|
||||
// https://www.cs.cmu.edu/~410/doc/doxygen.html
|
||||
match style {
|
||||
DocumentationStyle::C => {
|
||||
out.write("/*");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
DocumentationStyle::Doxy => {
|
||||
out.write("/**");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
for line in &self.doc_comment {
|
||||
match style {
|
||||
DocumentationStyle::C => out.write(""),
|
||||
DocumentationStyle::Doxy => out.write(" *"),
|
||||
DocumentationStyle::C99 => out.write("//"),
|
||||
DocumentationStyle::Cxx => out.write("///"),
|
||||
DocumentationStyle::Auto => unreachable!(), // Auto case should always be covered
|
||||
}
|
||||
|
||||
write!(out, "{}", line);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
match style {
|
||||
DocumentationStyle::C => {
|
||||
out.write(" */");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
DocumentationStyle::Doxy => {
|
||||
out.write(" */");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
1503
zeroidc/vendor/cbindgen/src/bindgen/ir/enumeration.rs
vendored
Normal file
1503
zeroidc/vendor/cbindgen/src/bindgen/ir/enumeration.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
77
zeroidc/vendor/cbindgen/src/bindgen/ir/field.rs
vendored
Normal file
77
zeroidc/vendor/cbindgen/src/bindgen/ir/field.rs
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::cdecl;
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::ir::{AnnotationSet, Cfg, ConditionWrite};
|
||||
use crate::bindgen::ir::{Documentation, Path, ToCondition, Type};
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Field {
|
||||
pub name: String,
|
||||
pub ty: Type,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub fn from_name_and_type(name: String, ty: Type) -> Field {
|
||||
Field {
|
||||
name,
|
||||
ty,
|
||||
cfg: None,
|
||||
annotations: AnnotationSet::new(),
|
||||
documentation: Documentation::none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(field: &syn::Field, self_path: &Path) -> Result<Option<Field>, String> {
|
||||
Ok(if let Some(mut ty) = Type::load(&field.ty)? {
|
||||
ty.replace_self_with(self_path);
|
||||
Some(Field {
|
||||
name: field
|
||||
.ident
|
||||
.as_ref()
|
||||
.ok_or_else(|| "field is missing identifier".to_string())?
|
||||
.to_string(),
|
||||
ty,
|
||||
cfg: Cfg::load(&field.attrs),
|
||||
annotations: AnnotationSet::load(&field.attrs)?,
|
||||
documentation: Documentation::load(&field.attrs),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Field {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
// Cython doesn't support conditional fields.
|
||||
let condition = self.cfg.to_condition(config);
|
||||
if config.language != Language::Cython {
|
||||
condition.write_before(config, out);
|
||||
}
|
||||
|
||||
self.documentation.write(config, out);
|
||||
cdecl::write_field(out, &self.ty, &self.name, config);
|
||||
// Cython extern declarations don't manage layouts, layouts are defined entierly by the
|
||||
// corresponding C code. So we can omit bitfield sizes which are not supported by Cython.
|
||||
if config.language != Language::Cython {
|
||||
if let Some(bitfield) = self.annotations.atom("bitfield") {
|
||||
write!(out, ": {}", bitfield.unwrap_or_default());
|
||||
}
|
||||
}
|
||||
|
||||
if config.language != Language::Cython {
|
||||
condition.write_after(config, out);
|
||||
// FIXME(#634): `write_vertical_source_list` should support
|
||||
// configuring list elements natively. For now we print a newline
|
||||
// here to avoid printing `#endif;` with semicolon.
|
||||
if condition.is_some() {
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
400
zeroidc/vendor/cbindgen/src/bindgen/ir/function.rs
vendored
Normal file
400
zeroidc/vendor/cbindgen/src/bindgen/ir/function.rs
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::cdecl;
|
||||
use crate::bindgen::config::{Config, Language, Layout};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericPath, Path, PrimitiveType,
|
||||
ToCondition, Type,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::rename::{IdentifierType, RenameRule};
|
||||
use crate::bindgen::reserved;
|
||||
use crate::bindgen::utilities::IterHelpers;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FunctionArgument {
|
||||
pub name: Option<String>,
|
||||
pub ty: Type,
|
||||
pub array_length: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Function {
|
||||
pub path: Path,
|
||||
/// Path to the self-type of the function
|
||||
/// If the function is a method, this will contain the path of the type in the impl block
|
||||
pub self_type_path: Option<Path>,
|
||||
pub ret: Type,
|
||||
pub args: Vec<FunctionArgument>,
|
||||
pub extern_decl: bool,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
pub never_return: bool,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn load(
|
||||
path: Path,
|
||||
self_type_path: Option<&Path>,
|
||||
sig: &syn::Signature,
|
||||
extern_decl: bool,
|
||||
attrs: &[syn::Attribute],
|
||||
mod_cfg: Option<&Cfg>,
|
||||
) -> Result<Function, String> {
|
||||
let mut args = sig.inputs.iter().try_skip_map(|x| x.as_argument())?;
|
||||
|
||||
let mut never_return = false;
|
||||
let mut ret = match sig.output {
|
||||
syn::ReturnType::Default => Type::Primitive(PrimitiveType::Void),
|
||||
syn::ReturnType::Type(_, ref ty) => {
|
||||
if let syn::Type::Never(_) = ty.as_ref() {
|
||||
never_return = true;
|
||||
Type::Primitive(PrimitiveType::Void)
|
||||
} else {
|
||||
Type::load(ty)?.unwrap_or(Type::Primitive(PrimitiveType::Void))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(self_path) = self_type_path {
|
||||
for arg in &mut args {
|
||||
arg.ty.replace_self_with(self_path);
|
||||
}
|
||||
ret.replace_self_with(self_path);
|
||||
}
|
||||
|
||||
Ok(Function {
|
||||
path,
|
||||
self_type_path: self_type_path.cloned(),
|
||||
ret,
|
||||
args,
|
||||
extern_decl,
|
||||
cfg: Cfg::append(mod_cfg, Cfg::load(attrs)),
|
||||
annotations: AnnotationSet::load(attrs)?,
|
||||
documentation: Documentation::load(attrs),
|
||||
never_return,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn never_return(&self, config: &Config) -> bool {
|
||||
self.never_return && config.language != Language::Cython
|
||||
}
|
||||
|
||||
pub fn swift_name(&self, config: &Config) -> Option<String> {
|
||||
if config.language == Language::Cython {
|
||||
return None;
|
||||
}
|
||||
// If the symbol name starts with the type name, separate the two components with '.'
|
||||
// so that Swift recognises the association between the method and the type
|
||||
let (ref type_prefix, ref type_name) = match self.self_type_path {
|
||||
Some(ref type_name) => {
|
||||
let type_name = type_name.to_string();
|
||||
if !self.path.name().starts_with(&type_name) {
|
||||
return Some(self.path.to_string());
|
||||
}
|
||||
(format!("{}.", type_name), type_name)
|
||||
}
|
||||
None => ("".to_string(), "".to_string()),
|
||||
};
|
||||
|
||||
let item_name = self
|
||||
.path
|
||||
.name()
|
||||
.trim_start_matches(type_name)
|
||||
.trim_start_matches('_');
|
||||
|
||||
let item_args = {
|
||||
let mut items = Vec::with_capacity(self.args.len());
|
||||
for arg in self.args.iter() {
|
||||
items.push(format!("{}:", arg.name.as_ref()?.as_str()));
|
||||
}
|
||||
items.join("")
|
||||
};
|
||||
Some(format!("{}{}({})", type_prefix, item_name, item_args))
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
self.ret.simplify_standard_types(config);
|
||||
for arg in &mut self.args {
|
||||
arg.ty.simplify_standard_types(config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.ret.add_dependencies(library, out);
|
||||
for arg in &self.args {
|
||||
arg.ty.add_dependencies(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
|
||||
self.ret.add_monomorphs(library, out);
|
||||
for arg in &self.args {
|
||||
arg.ty.add_monomorphs(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
self.ret.mangle_paths(monomorphs);
|
||||
for arg in &mut self.args {
|
||||
arg.ty.mangle_paths(monomorphs);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ret.resolve_declaration_types(resolver);
|
||||
for arg in &mut self.args {
|
||||
arg.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config) {
|
||||
// Rename the types used in arguments
|
||||
let generic_params = Default::default();
|
||||
self.ret.rename_for_config(config, &generic_params);
|
||||
|
||||
// Apply rename rules to argument names
|
||||
let rules = self
|
||||
.annotations
|
||||
.parse_atom::<RenameRule>("rename-all")
|
||||
.unwrap_or(config.function.rename_args);
|
||||
|
||||
if let Some(r) = rules.not_none() {
|
||||
let args = std::mem::take(&mut self.args);
|
||||
self.args = args
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let name = arg
|
||||
.name
|
||||
.map(|n| r.apply(&n, IdentifierType::FunctionArg).into_owned());
|
||||
FunctionArgument {
|
||||
name,
|
||||
ty: arg.ty,
|
||||
array_length: None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// Escape C/C++ reserved keywords used in argument names, and
|
||||
// recursively rename argument types.
|
||||
for arg in &mut self.args {
|
||||
arg.ty.rename_for_config(config, &generic_params);
|
||||
if let Some(ref mut name) = arg.name {
|
||||
reserved::escape(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the array length of the pointer arguments which need to use
|
||||
// the C-array notation
|
||||
if let Some(tuples) = self.annotations.list("ptrs-as-arrays") {
|
||||
let mut ptrs_as_arrays: HashMap<String, String> = HashMap::new();
|
||||
for str_tuple in tuples {
|
||||
let parts: Vec<&str> = str_tuple[1..str_tuple.len() - 1]
|
||||
.split(';')
|
||||
.map(|x| x.trim())
|
||||
.collect();
|
||||
if parts.len() != 2 {
|
||||
warn!(
|
||||
"{:?} does not follow the correct syntax, so the annotation is being ignored",
|
||||
parts
|
||||
);
|
||||
continue;
|
||||
}
|
||||
ptrs_as_arrays.insert(parts[0].to_string(), parts[1].to_string());
|
||||
}
|
||||
|
||||
for arg in &mut self.args {
|
||||
match arg.ty {
|
||||
Type::Ptr { .. } => {}
|
||||
_ => continue,
|
||||
}
|
||||
let name = match arg.name {
|
||||
Some(ref name) => name,
|
||||
None => continue,
|
||||
};
|
||||
arg.array_length = ptrs_as_arrays.get(name).cloned();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Function {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
fn write_1<W: Write>(func: &Function, config: &Config, out: &mut SourceWriter<W>) {
|
||||
let prefix = config.function.prefix(&func.annotations);
|
||||
let postfix = config.function.postfix(&func.annotations);
|
||||
|
||||
let condition = func.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
func.documentation.write(config, out);
|
||||
|
||||
if func.extern_decl {
|
||||
out.write("extern ");
|
||||
} else {
|
||||
if let Some(ref prefix) = prefix {
|
||||
write!(out, "{} ", prefix);
|
||||
}
|
||||
if func.annotations.must_use(config) {
|
||||
if let Some(ref anno) = config.function.must_use {
|
||||
write!(out, "{} ", anno);
|
||||
}
|
||||
}
|
||||
}
|
||||
cdecl::write_func(out, func, false, config);
|
||||
|
||||
if !func.extern_decl {
|
||||
if let Some(ref postfix) = postfix {
|
||||
write!(out, " {}", postfix);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref swift_name_macro) = config.function.swift_name_macro {
|
||||
if let Some(swift_name) = func.swift_name(config) {
|
||||
write!(out, " {}({})", swift_name_macro, swift_name);
|
||||
}
|
||||
}
|
||||
|
||||
if func.never_return(config) {
|
||||
if let Some(ref no_return_attr) = config.function.no_return {
|
||||
out.write_fmt(format_args!(" {}", no_return_attr));
|
||||
}
|
||||
}
|
||||
|
||||
out.write(";");
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
|
||||
fn write_2<W: Write>(func: &Function, config: &Config, out: &mut SourceWriter<W>) {
|
||||
let prefix = config.function.prefix(&func.annotations);
|
||||
let postfix = config.function.postfix(&func.annotations);
|
||||
|
||||
let condition = func.cfg.to_condition(config);
|
||||
|
||||
condition.write_before(config, out);
|
||||
|
||||
func.documentation.write(config, out);
|
||||
|
||||
if func.extern_decl {
|
||||
out.write("extern ");
|
||||
} else {
|
||||
if let Some(ref prefix) = prefix {
|
||||
write!(out, "{}", prefix);
|
||||
out.new_line();
|
||||
}
|
||||
if func.annotations.must_use(config) {
|
||||
if let Some(ref anno) = config.function.must_use {
|
||||
write!(out, "{}", anno);
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
}
|
||||
cdecl::write_func(out, func, true, config);
|
||||
if !func.extern_decl {
|
||||
if let Some(ref postfix) = postfix {
|
||||
out.new_line();
|
||||
write!(out, "{}", postfix);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref swift_name_macro) = config.function.swift_name_macro {
|
||||
if let Some(swift_name) = func.swift_name(config) {
|
||||
write!(out, " {}({})", swift_name_macro, swift_name);
|
||||
}
|
||||
}
|
||||
|
||||
if func.never_return(config) {
|
||||
if let Some(ref no_return_attr) = config.function.no_return {
|
||||
out.write_fmt(format_args!(" {}", no_return_attr));
|
||||
}
|
||||
}
|
||||
|
||||
out.write(";");
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
|
||||
let option_1 = out.measure(|out| write_1(self, config, out));
|
||||
|
||||
if (config.function.args == Layout::Auto && option_1 <= config.line_length)
|
||||
|| config.function.args == Layout::Horizontal
|
||||
{
|
||||
write_1(self, config, out);
|
||||
} else {
|
||||
write_2(self, config, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait SynFnArgHelpers {
|
||||
fn as_argument(&self) -> Result<Option<FunctionArgument>, String>;
|
||||
}
|
||||
|
||||
fn gen_self_type(receiver: &syn::Receiver) -> Type {
|
||||
let self_ty = Type::Path(GenericPath::self_path());
|
||||
if receiver.reference.is_none() {
|
||||
return self_ty;
|
||||
}
|
||||
|
||||
let is_const = receiver.mutability.is_none();
|
||||
Type::Ptr {
|
||||
ty: Box::new(self_ty),
|
||||
is_const,
|
||||
is_nullable: false,
|
||||
is_ref: false,
|
||||
}
|
||||
}
|
||||
|
||||
impl SynFnArgHelpers for syn::FnArg {
|
||||
fn as_argument(&self) -> Result<Option<FunctionArgument>, String> {
|
||||
match *self {
|
||||
syn::FnArg::Typed(syn::PatType {
|
||||
ref pat, ref ty, ..
|
||||
}) => {
|
||||
let name = match **pat {
|
||||
syn::Pat::Wild(..) => None,
|
||||
syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => Some(ident.to_string()),
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"Parameter has an unsupported argument name: {:?}",
|
||||
pat
|
||||
))
|
||||
}
|
||||
};
|
||||
let ty = match Type::load(ty)? {
|
||||
Some(x) => x,
|
||||
None => return Ok(None),
|
||||
};
|
||||
if let Type::Array(..) = ty {
|
||||
return Err("Array as function arguments are not supported".to_owned());
|
||||
}
|
||||
Ok(Some(FunctionArgument {
|
||||
name,
|
||||
ty,
|
||||
array_length: None,
|
||||
}))
|
||||
}
|
||||
syn::FnArg::Receiver(ref receiver) => Ok(Some(FunctionArgument {
|
||||
name: Some("self".to_string()),
|
||||
ty: gen_self_type(receiver),
|
||||
array_length: None,
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
169
zeroidc/vendor/cbindgen/src/bindgen/ir/generic_path.rs
vendored
Normal file
169
zeroidc/vendor/cbindgen/src/bindgen/ir/generic_path.rs
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
use std::io::Write;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
|
||||
use crate::bindgen::ir::{Path, Type};
|
||||
use crate::bindgen::utilities::IterHelpers;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct GenericParams(pub Vec<Path>);
|
||||
|
||||
impl GenericParams {
|
||||
pub fn new(generics: &syn::Generics) -> Self {
|
||||
GenericParams(
|
||||
generics
|
||||
.params
|
||||
.iter()
|
||||
.filter_map(|x| match *x {
|
||||
syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => {
|
||||
Some(Path::new(ident.to_string()))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn write_internal<F: Write>(
|
||||
&self,
|
||||
config: &Config,
|
||||
out: &mut SourceWriter<F>,
|
||||
with_default: bool,
|
||||
) {
|
||||
if !self.0.is_empty() && config.language == Language::Cxx {
|
||||
out.write("template<");
|
||||
for (i, item) in self.0.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(", ");
|
||||
}
|
||||
write!(out, "typename {}", item);
|
||||
if with_default {
|
||||
write!(out, " = void");
|
||||
}
|
||||
}
|
||||
out.write(">");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
self.write_internal(config, out, true);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GenericParams {
|
||||
type Target = [Path];
|
||||
|
||||
fn deref(&self) -> &[Path] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for GenericParams {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
self.write_internal(config, out, false);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct GenericPath {
|
||||
path: Path,
|
||||
export_name: String,
|
||||
generics: Vec<Type>,
|
||||
ctype: Option<DeclarationType>,
|
||||
}
|
||||
|
||||
impl GenericPath {
|
||||
pub fn new(path: Path, generics: Vec<Type>) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
generics,
|
||||
ctype: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn self_path() -> Self {
|
||||
Self::new(Path::new("Self"), vec![])
|
||||
}
|
||||
|
||||
pub fn replace_self_with(&mut self, self_ty: &Path) {
|
||||
if self.path.replace_self_with(self_ty) {
|
||||
self.export_name = self_ty.name().to_owned();
|
||||
}
|
||||
// Caller deals with generics.
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn generics(&self) -> &[Type] {
|
||||
&self.generics
|
||||
}
|
||||
|
||||
pub fn generics_mut(&mut self) -> &mut [Type] {
|
||||
&mut self.generics
|
||||
}
|
||||
|
||||
pub fn ctype(&self) -> Option<&DeclarationType> {
|
||||
self.ctype.as_ref()
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
self.path.name()
|
||||
}
|
||||
|
||||
pub fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
|
||||
for generic in &mut self.generics {
|
||||
generic.rename_for_config(config, generic_params);
|
||||
}
|
||||
if !generic_params.contains(&self.path) {
|
||||
config.export.rename(&mut self.export_name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ctype = resolver.type_for(&self.path);
|
||||
}
|
||||
|
||||
pub fn load(path: &syn::Path) -> Result<Self, String> {
|
||||
assert!(
|
||||
!path.segments.is_empty(),
|
||||
"{:?} doesn't have any segments",
|
||||
path
|
||||
);
|
||||
let last_segment = path.segments.last().unwrap();
|
||||
let name = last_segment.ident.to_string();
|
||||
|
||||
let path = Path::new(name);
|
||||
let phantom_data_path = Path::new("PhantomData");
|
||||
if path == phantom_data_path {
|
||||
return Ok(Self::new(path, Vec::new()));
|
||||
}
|
||||
|
||||
let generics = match last_segment.arguments {
|
||||
syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
|
||||
ref args,
|
||||
..
|
||||
}) => args.iter().try_skip_map(|x| match *x {
|
||||
syn::GenericArgument::Type(ref x) => Type::load(x),
|
||||
syn::GenericArgument::Lifetime(_) => Ok(None),
|
||||
_ => Err(format!("can't handle generic argument {:?}", x)),
|
||||
})?,
|
||||
syn::PathArguments::Parenthesized(_) => {
|
||||
return Err("Path contains parentheses.".to_owned());
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
Ok(Self::new(path, generics))
|
||||
}
|
||||
}
|
||||
117
zeroidc/vendor/cbindgen/src/bindgen/ir/global.rs
vendored
Normal file
117
zeroidc/vendor/cbindgen/src/bindgen/ir/global.rs
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::cdecl;
|
||||
use crate::bindgen::config::Config;
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Path, Type};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Static {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub ty: Type,
|
||||
pub mutable: bool,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
}
|
||||
|
||||
impl Static {
|
||||
pub fn load(item: &syn::ItemStatic, mod_cfg: Option<&Cfg>) -> Result<Static, String> {
|
||||
let ty = Type::load(&item.ty)?;
|
||||
|
||||
if ty.is_none() {
|
||||
return Err("Cannot have a zero sized static definition.".to_owned());
|
||||
}
|
||||
|
||||
Ok(Static::new(
|
||||
Path::new(item.ident.to_string()),
|
||||
ty.unwrap(),
|
||||
item.mutability.is_some(),
|
||||
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
|
||||
AnnotationSet::load(&item.attrs)?,
|
||||
Documentation::load(&item.attrs),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
path: Path,
|
||||
ty: Type,
|
||||
mutable: bool,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
ty,
|
||||
mutable,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
self.ty.simplify_standard_types(config);
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Static {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Static(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
self.ty.rename_for_config(config, &Default::default());
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.ty.add_dependencies(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Static {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
out.write("extern ");
|
||||
if let Type::Ptr { is_const: true, .. } = self.ty {
|
||||
} else if !self.mutable {
|
||||
out.write("const ");
|
||||
}
|
||||
cdecl::write_field(out, &self.ty, &self.export_name, config);
|
||||
out.write(";");
|
||||
}
|
||||
}
|
||||
244
zeroidc/vendor/cbindgen/src/bindgen/ir/item.rs
vendored
Normal file
244
zeroidc/vendor/cbindgen/src/bindgen/ir/item.rs
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 indexmap::IndexMap;
|
||||
use std::mem;
|
||||
|
||||
use crate::bindgen::config::Config;
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
|
||||
/// An item is any type of rust item besides a function
|
||||
pub trait Item {
|
||||
fn path(&self) -> &Path;
|
||||
fn name(&self) -> &str {
|
||||
self.path().name()
|
||||
}
|
||||
fn export_name(&self) -> &str {
|
||||
self.name()
|
||||
}
|
||||
fn cfg(&self) -> Option<&Cfg>;
|
||||
fn annotations(&self) -> &AnnotationSet;
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet;
|
||||
|
||||
fn container(&self) -> ItemContainer;
|
||||
|
||||
fn collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn rename_for_config(&mut self, _config: &Config) {}
|
||||
fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
|
||||
fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) {
|
||||
unreachable!("Cannot instantiate {} as a generic.", self.name())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ItemContainer {
|
||||
Constant(Constant),
|
||||
Static(Static),
|
||||
OpaqueItem(OpaqueItem),
|
||||
Struct(Struct),
|
||||
Union(Union),
|
||||
Enum(Enum),
|
||||
Typedef(Typedef),
|
||||
}
|
||||
|
||||
impl ItemContainer {
|
||||
pub fn deref(&self) -> &dyn Item {
|
||||
match *self {
|
||||
ItemContainer::Constant(ref x) => x,
|
||||
ItemContainer::Static(ref x) => x,
|
||||
ItemContainer::OpaqueItem(ref x) => x,
|
||||
ItemContainer::Struct(ref x) => x,
|
||||
ItemContainer::Union(ref x) => x,
|
||||
ItemContainer::Enum(ref x) => x,
|
||||
ItemContainer::Typedef(ref x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ItemValue<T: Item> {
|
||||
Cfg(Vec<T>),
|
||||
Single(T),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ItemMap<T: Item> {
|
||||
data: IndexMap<Path, ItemValue<T>>,
|
||||
}
|
||||
|
||||
impl<T: Item> Default for ItemMap<T> {
|
||||
fn default() -> ItemMap<T> {
|
||||
ItemMap {
|
||||
data: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Item + Clone> ItemMap<T> {
|
||||
pub fn rebuild(&mut self) {
|
||||
let old = mem::take(self);
|
||||
old.for_all_items(|x| {
|
||||
self.try_insert(x.clone());
|
||||
});
|
||||
}
|
||||
|
||||
pub fn try_insert(&mut self, item: T) -> bool {
|
||||
match (item.cfg().is_some(), self.data.get_mut(item.path())) {
|
||||
(true, Some(&mut ItemValue::Cfg(ref mut items))) => {
|
||||
items.push(item);
|
||||
return true;
|
||||
}
|
||||
(false, Some(&mut ItemValue::Cfg(_))) => {
|
||||
return false;
|
||||
}
|
||||
(true, Some(&mut ItemValue::Single(_))) => {
|
||||
return false;
|
||||
}
|
||||
(false, Some(&mut ItemValue::Single(_))) => {
|
||||
return false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let path = item.path().clone();
|
||||
if item.cfg().is_some() {
|
||||
self.data.insert(path, ItemValue::Cfg(vec![item]));
|
||||
} else {
|
||||
self.data.insert(path, ItemValue::Single(item));
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn extend_with(&mut self, other: &ItemMap<T>) {
|
||||
other.for_all_items(|x| {
|
||||
self.try_insert(x.clone());
|
||||
});
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<T> {
|
||||
let mut result = Vec::with_capacity(self.data.len());
|
||||
for container in self.data.values() {
|
||||
match *container {
|
||||
ItemValue::Cfg(ref items) => result.extend_from_slice(items),
|
||||
ItemValue::Single(ref item) => {
|
||||
result.push(item.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_items(&self, path: &Path) -> Option<Vec<ItemContainer>> {
|
||||
Some(match *self.data.get(path)? {
|
||||
ItemValue::Cfg(ref items) => items.iter().map(|x| x.container()).collect(),
|
||||
ItemValue::Single(ref item) => vec![item.container()],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn filter<F>(&mut self, callback: F)
|
||||
where
|
||||
F: Fn(&T) -> bool,
|
||||
{
|
||||
let data = mem::take(&mut self.data);
|
||||
|
||||
for (name, container) in data {
|
||||
match container {
|
||||
ItemValue::Cfg(items) => {
|
||||
let mut new_items = Vec::new();
|
||||
for item in items {
|
||||
if !callback(&item) {
|
||||
new_items.push(item);
|
||||
}
|
||||
}
|
||||
if !new_items.is_empty() {
|
||||
self.data.insert(name, ItemValue::Cfg(new_items));
|
||||
}
|
||||
}
|
||||
ItemValue::Single(item) => {
|
||||
if !callback(&item) {
|
||||
self.data.insert(name, ItemValue::Single(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_all_items<F>(&self, mut callback: F)
|
||||
where
|
||||
F: FnMut(&T),
|
||||
{
|
||||
for container in self.data.values() {
|
||||
match *container {
|
||||
ItemValue::Cfg(ref items) => {
|
||||
for item in items {
|
||||
callback(item);
|
||||
}
|
||||
}
|
||||
ItemValue::Single(ref item) => callback(item),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_all_items_mut<F>(&mut self, mut callback: F)
|
||||
where
|
||||
F: FnMut(&mut T),
|
||||
{
|
||||
for container in self.data.values_mut() {
|
||||
match *container {
|
||||
ItemValue::Cfg(ref mut items) => {
|
||||
for item in items {
|
||||
callback(item);
|
||||
}
|
||||
}
|
||||
ItemValue::Single(ref mut item) => callback(item),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_items<F>(&self, path: &Path, mut callback: F)
|
||||
where
|
||||
F: FnMut(&T),
|
||||
{
|
||||
match self.data.get(path) {
|
||||
Some(&ItemValue::Cfg(ref items)) => {
|
||||
for item in items {
|
||||
callback(item);
|
||||
}
|
||||
}
|
||||
Some(&ItemValue::Single(ref item)) => {
|
||||
callback(item);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_items_mut<F>(&mut self, path: &Path, mut callback: F)
|
||||
where
|
||||
F: FnMut(&mut T),
|
||||
{
|
||||
match self.data.get_mut(path) {
|
||||
Some(&mut ItemValue::Cfg(ref mut items)) => {
|
||||
for item in items {
|
||||
callback(item);
|
||||
}
|
||||
}
|
||||
Some(&mut ItemValue::Single(ref mut item)) => {
|
||||
callback(item);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
zeroidc/vendor/cbindgen/src/bindgen/ir/mod.rs
vendored
Normal file
39
zeroidc/vendor/cbindgen/src/bindgen/ir/mod.rs
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
pub mod annotation;
|
||||
pub mod cfg;
|
||||
pub mod constant;
|
||||
pub mod documentation;
|
||||
pub mod enumeration;
|
||||
pub mod field;
|
||||
pub mod function;
|
||||
pub mod generic_path;
|
||||
pub mod global;
|
||||
pub mod item;
|
||||
pub mod opaque;
|
||||
pub mod path;
|
||||
pub mod repr;
|
||||
pub mod structure;
|
||||
pub mod ty;
|
||||
pub mod typedef;
|
||||
pub mod union;
|
||||
|
||||
pub use self::annotation::{AnnotationSet, AnnotationValue};
|
||||
pub use self::cfg::*;
|
||||
pub use self::constant::*;
|
||||
pub use self::documentation::Documentation;
|
||||
pub use self::enumeration::*;
|
||||
pub use self::field::*;
|
||||
pub use self::function::*;
|
||||
pub use self::generic_path::*;
|
||||
pub use self::global::*;
|
||||
pub use self::item::*;
|
||||
pub use self::opaque::*;
|
||||
pub use self::path::*;
|
||||
pub use self::repr::*;
|
||||
pub use self::structure::*;
|
||||
pub use self::ty::*;
|
||||
pub use self::typedef::*;
|
||||
pub use self::union::*;
|
||||
176
zeroidc/vendor/cbindgen/src/bindgen/ir/opaque.rs
vendored
Normal file
176
zeroidc/vendor/cbindgen/src/bindgen/ir/opaque.rs
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
|
||||
ToCondition, Type,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::mangle;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OpaqueItem {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub generic_params: GenericParams,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
}
|
||||
|
||||
impl OpaqueItem {
|
||||
pub fn load(
|
||||
path: Path,
|
||||
generics: &syn::Generics,
|
||||
attrs: &[syn::Attribute],
|
||||
mod_cfg: Option<&Cfg>,
|
||||
) -> Result<OpaqueItem, String> {
|
||||
Ok(Self::new(
|
||||
path,
|
||||
GenericParams::new(generics),
|
||||
Cfg::append(mod_cfg, Cfg::load(attrs)),
|
||||
AnnotationSet::load(attrs).unwrap_or_else(|_| AnnotationSet::new()),
|
||||
Documentation::load(attrs),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
path: Path,
|
||||
generic_params: GenericParams,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
) -> OpaqueItem {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
generic_params,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for OpaqueItem {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::OpaqueItem(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_struct(&self.path);
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.export_name);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, _: &Library, _: &mut Dependencies) {}
|
||||
|
||||
fn instantiate_monomorph(
|
||||
&self,
|
||||
generic_values: &[Type],
|
||||
library: &Library,
|
||||
out: &mut Monomorphs,
|
||||
) {
|
||||
assert!(
|
||||
!self.generic_params.is_empty(),
|
||||
"{} is not generic",
|
||||
self.path
|
||||
);
|
||||
|
||||
// We can be instantiated with less generic params because of default
|
||||
// template parameters, or because of empty types that we remove during
|
||||
// parsing (`()`).
|
||||
assert!(
|
||||
self.generic_params.len() >= generic_values.len(),
|
||||
"{} has {} params but is being instantiated with {} values",
|
||||
self.path,
|
||||
self.generic_params.len(),
|
||||
generic_values.len(),
|
||||
);
|
||||
|
||||
let mangled_path = mangle::mangle_path(
|
||||
&self.path,
|
||||
generic_values,
|
||||
&library.get_config().export.mangle,
|
||||
);
|
||||
|
||||
let monomorph = OpaqueItem::new(
|
||||
mangled_path,
|
||||
GenericParams::default(),
|
||||
self.cfg.clone(),
|
||||
self.annotations.clone(),
|
||||
self.documentation.clone(),
|
||||
);
|
||||
|
||||
out.insert_opaque(self, monomorph, generic_values.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for OpaqueItem {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
let condition = self.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
self.generic_params.write_with_default(config, out);
|
||||
|
||||
match config.language {
|
||||
Language::C if config.style.generate_typedef() => {
|
||||
write!(
|
||||
out,
|
||||
"typedef struct {} {};",
|
||||
self.export_name(),
|
||||
self.export_name()
|
||||
);
|
||||
}
|
||||
Language::C | Language::Cxx => {
|
||||
write!(out, "struct {};", self.export_name());
|
||||
}
|
||||
Language::Cython => {
|
||||
write!(
|
||||
out,
|
||||
"{}struct {}",
|
||||
config.style.cython_def(),
|
||||
self.export_name()
|
||||
);
|
||||
out.open_brace();
|
||||
out.write("pass");
|
||||
out.close_brace(false);
|
||||
}
|
||||
}
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
}
|
||||
50
zeroidc/vendor/cbindgen/src/bindgen/ir/path.rs
vendored
Normal file
50
zeroidc/vendor/cbindgen/src/bindgen/ir/path.rs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Path {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
pub fn new<T>(name: T) -> Self
|
||||
where
|
||||
String: From<T>,
|
||||
{
|
||||
Self { name: name.into() }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn replace_self_with(&mut self, path: &Self) -> bool {
|
||||
if self.name() != "Self" {
|
||||
return false;
|
||||
}
|
||||
*self = path.clone();
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Path {
|
||||
fn partial_cmp(&self, other: &Path) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Path {
|
||||
fn cmp(&self, other: &Path) -> Ordering {
|
||||
self.name.cmp(&other.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Path {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
184
zeroidc/vendor/cbindgen/src/bindgen/ir/repr.rs
vendored
Normal file
184
zeroidc/vendor/cbindgen/src/bindgen/ir/repr.rs
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 crate::bindgen::ir::ty::{IntKind, PrimitiveType};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ReprStyle {
|
||||
Rust,
|
||||
C,
|
||||
Transparent,
|
||||
}
|
||||
|
||||
impl Default for ReprStyle {
|
||||
fn default() -> Self {
|
||||
ReprStyle::Rust
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ReprType {
|
||||
kind: IntKind,
|
||||
signed: bool,
|
||||
}
|
||||
|
||||
impl ReprType {
|
||||
pub(crate) fn to_primitive(self) -> PrimitiveType {
|
||||
PrimitiveType::Integer {
|
||||
kind: self.kind,
|
||||
signed: self.signed,
|
||||
zeroable: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ReprAlign {
|
||||
Packed,
|
||||
Align(u64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||
pub struct Repr {
|
||||
pub style: ReprStyle,
|
||||
pub ty: Option<ReprType>,
|
||||
pub align: Option<ReprAlign>,
|
||||
}
|
||||
|
||||
impl Repr {
|
||||
pub fn load(attrs: &[syn::Attribute]) -> Result<Repr, String> {
|
||||
let ids = attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if let syn::Meta::List(syn::MetaList { path, nested, .. }) =
|
||||
attr.parse_meta().ok()?
|
||||
{
|
||||
if path.is_ident("repr") {
|
||||
return Some(nested.into_iter().collect::<Vec<_>>());
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.flatten()
|
||||
.filter_map(|meta| match meta {
|
||||
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
|
||||
Some((path.segments.first().unwrap().ident.to_string(), None))
|
||||
}
|
||||
syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList { path, nested, .. })) => {
|
||||
Some((
|
||||
path.segments.first().unwrap().ident.to_string(),
|
||||
Some(
|
||||
nested
|
||||
.iter()
|
||||
.filter_map(|meta| match meta {
|
||||
// Only used for #[repr(align(...))].
|
||||
syn::NestedMeta::Lit(syn::Lit::Int(literal)) => {
|
||||
Some(literal.base10_digits().to_string())
|
||||
}
|
||||
// Only single levels of nesting supported at the moment.
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
),
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let mut repr = Repr::default();
|
||||
for id in ids {
|
||||
let (int_kind, signed) = match (id.0.as_ref(), id.1) {
|
||||
("u8", None) => (IntKind::B8, false),
|
||||
("u16", None) => (IntKind::B16, false),
|
||||
("u32", None) => (IntKind::B32, false),
|
||||
("u64", None) => (IntKind::B64, false),
|
||||
("usize", None) => (IntKind::Size, false),
|
||||
("i8", None) => (IntKind::B8, true),
|
||||
("i16", None) => (IntKind::B16, true),
|
||||
("i32", None) => (IntKind::B32, true),
|
||||
("i64", None) => (IntKind::B64, true),
|
||||
("isize", None) => (IntKind::Size, true),
|
||||
("C", None) => {
|
||||
repr.style = ReprStyle::C;
|
||||
continue;
|
||||
}
|
||||
("transparent", None) => {
|
||||
repr.style = ReprStyle::Transparent;
|
||||
continue;
|
||||
}
|
||||
("packed", args) => {
|
||||
// #[repr(packed(n))] not supported because of some open questions about how
|
||||
// to calculate the native alignment of types. See eqrion/cbindgen#433.
|
||||
if args.is_some() {
|
||||
return Err(
|
||||
"Not-yet-implemented #[repr(packed(...))] encountered.".to_string()
|
||||
);
|
||||
}
|
||||
let align = ReprAlign::Packed;
|
||||
// Only permit a single alignment-setting repr.
|
||||
if let Some(old_align) = repr.align {
|
||||
return Err(format!(
|
||||
"Conflicting #[repr(align(...))] type hints {:?} and {:?}.",
|
||||
old_align, align
|
||||
));
|
||||
}
|
||||
repr.align = Some(align);
|
||||
continue;
|
||||
}
|
||||
("align", Some(args)) => {
|
||||
// #[repr(align(...))] only allows a single argument.
|
||||
if args.len() != 1 {
|
||||
return Err(format!(
|
||||
"Unsupported #[repr(align({}))], align must have exactly one argument.",
|
||||
args.join(", ")
|
||||
));
|
||||
}
|
||||
// Must be a positive integer.
|
||||
let align = match args.first().unwrap().parse::<u64>() {
|
||||
Ok(align) => align,
|
||||
Err(_) => {
|
||||
return Err(format!("Non-numeric #[repr(align({}))].", args.join(", ")))
|
||||
}
|
||||
};
|
||||
// Must be a power of 2.
|
||||
if !align.is_power_of_two() || align == 0 {
|
||||
return Err(format!("Invalid alignment to #[repr(align({}))].", align));
|
||||
}
|
||||
// Only permit a single alignment-setting repr.
|
||||
if let Some(old_align) = repr.align {
|
||||
return Err(format!(
|
||||
"Conflicting #[repr(align(...))] type hints {:?} and {:?}.",
|
||||
old_align,
|
||||
ReprAlign::Align(align)
|
||||
));
|
||||
}
|
||||
repr.align = Some(ReprAlign::Align(align));
|
||||
continue;
|
||||
}
|
||||
(path, args) => match args {
|
||||
None => return Err(format!("Unsupported #[repr({})].", path)),
|
||||
Some(args) => {
|
||||
return Err(format!(
|
||||
"Unsupported #[repr({}({}))].",
|
||||
path,
|
||||
args.join(", ")
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let ty = ReprType {
|
||||
kind: int_kind,
|
||||
signed,
|
||||
};
|
||||
if let Some(old_ty) = repr.ty {
|
||||
return Err(format!(
|
||||
"Conflicting #[repr(...)] type hints {:?} and {:?}.",
|
||||
old_ty, ty
|
||||
));
|
||||
}
|
||||
repr.ty = Some(ty);
|
||||
}
|
||||
Ok(repr)
|
||||
}
|
||||
}
|
||||
710
zeroidc/vendor/cbindgen/src/bindgen/ir/structure.rs
vendored
Normal file
710
zeroidc/vendor/cbindgen/src/bindgen/ir/structure.rs
vendored
Normal file
@@ -0,0 +1,710 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Config, Language, LayoutConfig};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, Field, GenericParams, Item,
|
||||
ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, Typedef,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::mangle;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::rename::{IdentifierType, RenameRule};
|
||||
use crate::bindgen::reserved;
|
||||
use crate::bindgen::utilities::IterHelpers;
|
||||
use crate::bindgen::writer::{ListType, Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Struct {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub generic_params: GenericParams,
|
||||
pub fields: Vec<Field>,
|
||||
/// Whether there's a tag field on the body of this struct. When this is
|
||||
/// true, is_enum_variant_body is also guaranteed to be true.
|
||||
pub has_tag_field: bool,
|
||||
/// Whether this is an enum variant body.
|
||||
pub is_enum_variant_body: bool,
|
||||
pub alignment: Option<ReprAlign>,
|
||||
pub is_transparent: bool,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
pub associated_constants: Vec<Constant>,
|
||||
}
|
||||
|
||||
impl Struct {
|
||||
/// Whether this struct can derive operator== / operator!=.
|
||||
pub fn can_derive_eq(&self) -> bool {
|
||||
!self.fields.is_empty() && self.fields.iter().all(|x| x.ty.can_cmp_eq())
|
||||
}
|
||||
|
||||
pub fn add_associated_constant(&mut self, c: Constant) {
|
||||
self.associated_constants.push(c);
|
||||
}
|
||||
|
||||
pub fn load(
|
||||
layout_config: &LayoutConfig,
|
||||
item: &syn::ItemStruct,
|
||||
mod_cfg: Option<&Cfg>,
|
||||
) -> Result<Self, String> {
|
||||
let repr = Repr::load(&item.attrs)?;
|
||||
let is_transparent = match repr.style {
|
||||
ReprStyle::C => false,
|
||||
ReprStyle::Transparent => true,
|
||||
_ => {
|
||||
return Err("Struct is not marked #[repr(C)] or #[repr(transparent)].".to_owned());
|
||||
}
|
||||
};
|
||||
|
||||
let path = Path::new(item.ident.to_string());
|
||||
|
||||
// Ensure we can safely represent the struct given the configuration.
|
||||
if let Some(align) = repr.align {
|
||||
layout_config.ensure_safe_to_represent(&align)?;
|
||||
}
|
||||
|
||||
let fields = match item.fields {
|
||||
syn::Fields::Unit => Vec::new(),
|
||||
syn::Fields::Named(ref fields) => fields
|
||||
.named
|
||||
.iter()
|
||||
.try_skip_map(|field| Field::load(field, &path))?,
|
||||
syn::Fields::Unnamed(ref fields) => {
|
||||
let mut out = Vec::new();
|
||||
let mut current = 0;
|
||||
for field in fields.unnamed.iter() {
|
||||
if let Some(mut ty) = Type::load(&field.ty)? {
|
||||
ty.replace_self_with(&path);
|
||||
out.push(Field {
|
||||
name: format!("{}", current),
|
||||
ty,
|
||||
cfg: Cfg::load(&field.attrs),
|
||||
annotations: AnnotationSet::load(&field.attrs)?,
|
||||
documentation: Documentation::load(&field.attrs),
|
||||
});
|
||||
current += 1;
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
};
|
||||
|
||||
let has_tag_field = false;
|
||||
let is_enum_variant_body = false;
|
||||
|
||||
Ok(Struct::new(
|
||||
path,
|
||||
GenericParams::new(&item.generics),
|
||||
fields,
|
||||
has_tag_field,
|
||||
is_enum_variant_body,
|
||||
repr.align,
|
||||
is_transparent,
|
||||
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
|
||||
AnnotationSet::load(&item.attrs)?,
|
||||
Documentation::load(&item.attrs),
|
||||
))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
path: Path,
|
||||
generic_params: GenericParams,
|
||||
fields: Vec<Field>,
|
||||
has_tag_field: bool,
|
||||
is_enum_variant_body: bool,
|
||||
alignment: Option<ReprAlign>,
|
||||
is_transparent: bool,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
generic_params,
|
||||
fields,
|
||||
has_tag_field,
|
||||
is_enum_variant_body,
|
||||
alignment,
|
||||
is_transparent,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
associated_constants: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.simplify_standard_types(config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_generic(&self) -> bool {
|
||||
self.generic_params.len() > 0
|
||||
}
|
||||
|
||||
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
|
||||
// Generic structs can instantiate monomorphs only once they've been
|
||||
// instantiated. See `instantiate_monomorph` for more details.
|
||||
if self.is_generic() {
|
||||
return;
|
||||
}
|
||||
|
||||
for field in &self.fields {
|
||||
field.ty.add_monomorphs(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.mangle_paths(monomorphs);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn specialize(
|
||||
&self,
|
||||
generic_values: &[Type],
|
||||
mappings: &[(&Path, &Type)],
|
||||
config: &Config,
|
||||
) -> Self {
|
||||
let mangled_path = mangle::mangle_path(&self.path, generic_values, &config.export.mangle);
|
||||
Struct::new(
|
||||
mangled_path,
|
||||
GenericParams::default(),
|
||||
self.fields
|
||||
.iter()
|
||||
.map(|field| Field {
|
||||
name: field.name.clone(),
|
||||
ty: field.ty.specialize(mappings),
|
||||
cfg: field.cfg.clone(),
|
||||
annotations: field.annotations.clone(),
|
||||
documentation: field.documentation.clone(),
|
||||
})
|
||||
.collect(),
|
||||
self.has_tag_field,
|
||||
self.is_enum_variant_body,
|
||||
self.alignment,
|
||||
self.is_transparent,
|
||||
self.cfg.clone(),
|
||||
self.annotations.clone(),
|
||||
self.documentation.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn emit_bitflags_binop<F: Write>(
|
||||
&self,
|
||||
operator: char,
|
||||
other: &str,
|
||||
out: &mut SourceWriter<F>,
|
||||
) {
|
||||
out.new_line();
|
||||
write!(
|
||||
out,
|
||||
"{} operator{}(const {}& {}) const",
|
||||
self.export_name(),
|
||||
operator,
|
||||
self.export_name(),
|
||||
other
|
||||
);
|
||||
out.open_brace();
|
||||
write!(
|
||||
out,
|
||||
"return {{static_cast<decltype(bits)>(this->bits {} {}.bits)}};",
|
||||
operator, other
|
||||
);
|
||||
out.close_brace(false);
|
||||
|
||||
out.new_line();
|
||||
write!(
|
||||
out,
|
||||
"{}& operator{}=(const {}& {})",
|
||||
self.export_name(),
|
||||
operator,
|
||||
self.export_name(),
|
||||
other
|
||||
);
|
||||
out.open_brace();
|
||||
write!(out, "*this = (*this {} {});", operator, other);
|
||||
out.new_line();
|
||||
write!(out, "return *this;");
|
||||
out.close_brace(false);
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Struct {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Struct(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
if self.is_transparent {
|
||||
resolver.add_none(&self.path);
|
||||
} else {
|
||||
resolver.add_struct(&self.path);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
// Rename the name of the struct
|
||||
if !(self.has_tag_field && config.language == Language::Cxx) {
|
||||
config.export.rename(&mut self.export_name);
|
||||
}
|
||||
|
||||
// Rename the types used in fields
|
||||
{
|
||||
let fields = self
|
||||
.fields
|
||||
.iter_mut()
|
||||
.skip(if self.has_tag_field { 1 } else { 0 });
|
||||
for field in fields {
|
||||
field.ty.rename_for_config(config, &self.generic_params);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply renaming rules to fields in the following order
|
||||
// 1. `cbindgen::field-names` annotation
|
||||
// 2. `cbindgen::rename-all` annotation
|
||||
// 3. config struct rename rule
|
||||
// If the struct is a tuple struct and we have not renamed the
|
||||
// fields, then prefix each of them with an underscore.
|
||||
// If any field is a reserved keyword, then postfix it with an
|
||||
// underscore.
|
||||
|
||||
// Scope for mutable borrow of fields
|
||||
{
|
||||
let names = self.fields.iter_mut().map(|field| &mut field.name);
|
||||
|
||||
let field_rules = self
|
||||
.annotations
|
||||
.parse_atom::<RenameRule>("rename-all")
|
||||
.unwrap_or(config.structure.rename_fields);
|
||||
|
||||
if let Some(o) = self.annotations.list("field-names") {
|
||||
for (dest, src) in names.zip(o) {
|
||||
*dest = src;
|
||||
}
|
||||
} else if let Some(r) = field_rules.not_none() {
|
||||
for name in names {
|
||||
*name = r.apply(name, IdentifierType::StructMember).into_owned();
|
||||
}
|
||||
} else {
|
||||
// If we don't have any rules for a tuple struct, prefix them with
|
||||
// an underscore so it still compiles.
|
||||
for name in names {
|
||||
if name.starts_with(|c: char| c.is_ascii_digit()) {
|
||||
name.insert(0, '_');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for field in &mut self.fields {
|
||||
reserved::escape(&mut field.name);
|
||||
}
|
||||
|
||||
for c in self.associated_constants.iter_mut() {
|
||||
c.rename_for_config(config);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
let mut fields = self.fields.iter();
|
||||
|
||||
// If there is a tag field, skip it
|
||||
if self.has_tag_field {
|
||||
fields.next();
|
||||
}
|
||||
|
||||
for field in fields {
|
||||
field
|
||||
.ty
|
||||
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
|
||||
}
|
||||
|
||||
for c in &self.associated_constants {
|
||||
c.add_dependencies(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
fn instantiate_monomorph(
|
||||
&self,
|
||||
generic_values: &[Type],
|
||||
library: &Library,
|
||||
out: &mut Monomorphs,
|
||||
) {
|
||||
assert!(
|
||||
self.generic_params.len() > 0,
|
||||
"{} is not generic",
|
||||
self.path
|
||||
);
|
||||
assert!(
|
||||
self.generic_params.len() == generic_values.len(),
|
||||
"{} has {} params but is being instantiated with {} values",
|
||||
self.path,
|
||||
self.generic_params.len(),
|
||||
generic_values.len(),
|
||||
);
|
||||
|
||||
let mappings = self
|
||||
.generic_params
|
||||
.iter()
|
||||
.zip(generic_values.iter())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let monomorph = self.specialize(generic_values, &mappings, library.get_config());
|
||||
out.insert_struct(library, self, monomorph, generic_values.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Struct {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
if self.is_transparent {
|
||||
let typedef = Typedef {
|
||||
path: self.path.clone(),
|
||||
export_name: self.export_name.to_owned(),
|
||||
generic_params: self.generic_params.clone(),
|
||||
aliased: self.fields[0].ty.clone(),
|
||||
cfg: self.cfg.clone(),
|
||||
annotations: self.annotations.clone(),
|
||||
documentation: self.documentation.clone(),
|
||||
};
|
||||
typedef.write(config, out);
|
||||
for constant in &self.associated_constants {
|
||||
out.new_line();
|
||||
constant.write(config, out, Some(self));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let condition = self.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
if !self.is_enum_variant_body {
|
||||
self.generic_params.write(config, out);
|
||||
}
|
||||
|
||||
// The following results in
|
||||
// C++ or C with Tag as style:
|
||||
// struct Name {
|
||||
// C with Type only style:
|
||||
// typedef struct {
|
||||
// C with Both as style:
|
||||
// typedef struct Name {
|
||||
match config.language {
|
||||
Language::C if config.style.generate_typedef() => out.write("typedef "),
|
||||
Language::C | Language::Cxx => {}
|
||||
Language::Cython => out.write(config.style.cython_def()),
|
||||
}
|
||||
|
||||
// Cython extern declarations don't manage layouts, layouts are defined entierly by the
|
||||
// corresponding C code. So this `packed` is only for documentation, and missing
|
||||
// `aligned(n)` is also not a problem.
|
||||
if config.language == Language::Cython {
|
||||
if let Some(align) = self.alignment {
|
||||
match align {
|
||||
ReprAlign::Packed => out.write("packed "),
|
||||
ReprAlign::Align(_) => {} // Not supported
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.write("struct");
|
||||
|
||||
if config.language != Language::Cython {
|
||||
if let Some(align) = self.alignment {
|
||||
match align {
|
||||
ReprAlign::Packed => {
|
||||
if let Some(ref anno) = config.layout.packed {
|
||||
write!(out, " {}", anno);
|
||||
}
|
||||
}
|
||||
ReprAlign::Align(n) => {
|
||||
if let Some(ref anno) = config.layout.aligned_n {
|
||||
write!(out, " {}({})", anno, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.annotations.must_use(config) {
|
||||
if let Some(ref anno) = config.structure.must_use {
|
||||
write!(out, " {}", anno);
|
||||
}
|
||||
}
|
||||
|
||||
if config.language != Language::C || config.style.generate_tag() {
|
||||
write!(out, " {}", self.export_name());
|
||||
}
|
||||
|
||||
out.open_brace();
|
||||
|
||||
// Emit the pre_body section, if relevant
|
||||
if let Some(body) = config.export.pre_body(&self.path) {
|
||||
out.write_raw_block(body);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
out.write_vertical_source_list(&self.fields, ListType::Cap(";"));
|
||||
if config.language == Language::Cython && self.fields.is_empty() {
|
||||
out.write("pass");
|
||||
}
|
||||
|
||||
if config.language == Language::Cxx {
|
||||
let mut wrote_start_newline = false;
|
||||
|
||||
if config.structure.derive_constructor(&self.annotations) && !self.fields.is_empty() {
|
||||
if !wrote_start_newline {
|
||||
wrote_start_newline = true;
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
out.new_line();
|
||||
|
||||
let arg_renamer = |name: &str| {
|
||||
config
|
||||
.function
|
||||
.rename_args
|
||||
.apply(name, IdentifierType::FunctionArg)
|
||||
.into_owned()
|
||||
};
|
||||
write!(out, "{}(", self.export_name());
|
||||
let vec: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
Field::from_name_and_type(
|
||||
// const-ref args to constructor
|
||||
format!("const& {}", arg_renamer(&field.name)),
|
||||
field.ty.clone(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
out.write_vertical_source_list(&vec[..], ListType::Join(","));
|
||||
write!(out, ")");
|
||||
out.new_line();
|
||||
write!(out, " : ");
|
||||
let vec: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| format!("{}({})", field.name, arg_renamer(&field.name)))
|
||||
.collect();
|
||||
out.write_vertical_source_list(&vec[..], ListType::Join(","));
|
||||
out.new_line();
|
||||
write!(out, "{{}}");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
let other = config
|
||||
.function
|
||||
.rename_args
|
||||
.apply("other", IdentifierType::FunctionArg);
|
||||
|
||||
if self
|
||||
.annotations
|
||||
.bool("internal-derive-bitflags")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if !wrote_start_newline {
|
||||
wrote_start_newline = true;
|
||||
out.new_line();
|
||||
}
|
||||
out.new_line();
|
||||
write!(out, "explicit operator bool() const");
|
||||
out.open_brace();
|
||||
write!(out, "return !!bits;");
|
||||
out.close_brace(false);
|
||||
|
||||
out.new_line();
|
||||
write!(out, "{} operator~() const", self.export_name());
|
||||
out.open_brace();
|
||||
write!(out, "return {{static_cast<decltype(bits)>(~bits)}};");
|
||||
out.close_brace(false);
|
||||
|
||||
self.emit_bitflags_binop('|', &other, out);
|
||||
self.emit_bitflags_binop('&', &other, out);
|
||||
self.emit_bitflags_binop('^', &other, out);
|
||||
}
|
||||
|
||||
// Generate a serializer function that allows dumping this struct
|
||||
// to an std::ostream. It's defined as a friend function inside the
|
||||
// struct definition, and doesn't need the `inline` keyword even
|
||||
// though it's implemented right in the generated header file.
|
||||
if config.structure.derive_ostream(&self.annotations) {
|
||||
if !wrote_start_newline {
|
||||
wrote_start_newline = true;
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
out.new_line();
|
||||
let stream = config
|
||||
.function
|
||||
.rename_args
|
||||
.apply("stream", IdentifierType::FunctionArg);
|
||||
let instance = config
|
||||
.function
|
||||
.rename_args
|
||||
.apply("instance", IdentifierType::FunctionArg);
|
||||
write!(
|
||||
out,
|
||||
"friend std::ostream& operator<<(std::ostream& {}, const {}& {})",
|
||||
stream,
|
||||
self.export_name(),
|
||||
instance,
|
||||
);
|
||||
out.open_brace();
|
||||
write!(out, "return {} << \"{{ \"", stream);
|
||||
let vec: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|x| format!(" << \"{}=\" << {}.{}", x.name, instance, x.name))
|
||||
.collect();
|
||||
out.write_vertical_source_list(&vec[..], ListType::Join(" << \", \""));
|
||||
out.write(" << \" }\";");
|
||||
out.close_brace(false);
|
||||
}
|
||||
|
||||
let skip_fields = if self.has_tag_field { 1 } else { 0 };
|
||||
|
||||
macro_rules! emit_op {
|
||||
($op_name:expr, $op:expr, $conjuc:expr) => {{
|
||||
if !wrote_start_newline {
|
||||
#[allow(unused_assignments)]
|
||||
{
|
||||
wrote_start_newline = true;
|
||||
}
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
out.new_line();
|
||||
|
||||
if let Some(Some(attrs)) =
|
||||
self.annotations.atom(concat!($op_name, "-attributes"))
|
||||
{
|
||||
write!(out, "{} ", attrs);
|
||||
}
|
||||
|
||||
write!(
|
||||
out,
|
||||
"bool operator{}(const {}& {}) const",
|
||||
$op,
|
||||
self.export_name(),
|
||||
other
|
||||
);
|
||||
out.open_brace();
|
||||
out.write("return ");
|
||||
let vec: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.skip(skip_fields)
|
||||
.map(|field| format!("{} {} {}.{}", field.name, $op, other, field.name))
|
||||
.collect();
|
||||
out.write_vertical_source_list(
|
||||
&vec[..],
|
||||
ListType::Join(&format!(" {}", $conjuc)),
|
||||
);
|
||||
out.write(";");
|
||||
out.close_brace(false);
|
||||
}};
|
||||
}
|
||||
|
||||
if config.structure.derive_eq(&self.annotations) && self.can_derive_eq() {
|
||||
emit_op!("eq", "==", "&&");
|
||||
}
|
||||
if config.structure.derive_neq(&self.annotations) && self.can_derive_eq() {
|
||||
emit_op!("neq", "!=", "||");
|
||||
}
|
||||
if config.structure.derive_lt(&self.annotations)
|
||||
&& self.fields.len() == 1
|
||||
&& self.fields[0].ty.can_cmp_order()
|
||||
{
|
||||
emit_op!("lt", "<", "&&");
|
||||
}
|
||||
if config.structure.derive_lte(&self.annotations)
|
||||
&& self.fields.len() == 1
|
||||
&& self.fields[0].ty.can_cmp_order()
|
||||
{
|
||||
emit_op!("lte", "<=", "&&");
|
||||
}
|
||||
if config.structure.derive_gt(&self.annotations)
|
||||
&& self.fields.len() == 1
|
||||
&& self.fields[0].ty.can_cmp_order()
|
||||
{
|
||||
emit_op!("gt", ">", "&&");
|
||||
}
|
||||
if config.structure.derive_gte(&self.annotations)
|
||||
&& self.fields.len() == 1
|
||||
&& self.fields[0].ty.can_cmp_order()
|
||||
{
|
||||
emit_op!("gte", ">=", "&&");
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the post_body section, if relevant
|
||||
if let Some(body) = config.export.post_body(&self.path) {
|
||||
out.new_line();
|
||||
out.write_raw_block(body);
|
||||
}
|
||||
|
||||
if config.language == Language::Cxx
|
||||
&& config.structure.associated_constants_in_body
|
||||
&& config.constant.allow_static_const
|
||||
{
|
||||
for constant in &self.associated_constants {
|
||||
out.new_line();
|
||||
constant.write_declaration(config, out, self);
|
||||
}
|
||||
}
|
||||
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.export_name());
|
||||
} else {
|
||||
out.close_brace(true);
|
||||
}
|
||||
|
||||
for constant in &self.associated_constants {
|
||||
out.new_line();
|
||||
constant.write(config, out, Some(self));
|
||||
}
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
}
|
||||
954
zeroidc/vendor/cbindgen/src/bindgen/ir/ty.rs
vendored
Normal file
954
zeroidc/vendor/cbindgen/src/bindgen/ir/ty.rs
vendored
Normal file
@@ -0,0 +1,954 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::cdecl;
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{GenericParams, GenericPath, Path};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::utilities::IterHelpers;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum PrimitiveType {
|
||||
Void,
|
||||
Bool,
|
||||
Char,
|
||||
SChar,
|
||||
UChar,
|
||||
Char32,
|
||||
Float,
|
||||
Double,
|
||||
VaList,
|
||||
PtrDiffT,
|
||||
Integer {
|
||||
zeroable: bool,
|
||||
signed: bool,
|
||||
kind: IntKind,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum IntKind {
|
||||
Short,
|
||||
Int,
|
||||
Long,
|
||||
LongLong,
|
||||
SizeT,
|
||||
Size,
|
||||
B8,
|
||||
B16,
|
||||
B32,
|
||||
B64,
|
||||
}
|
||||
|
||||
impl PrimitiveType {
|
||||
pub fn maybe(path: &str) -> Option<PrimitiveType> {
|
||||
Some(match path {
|
||||
"c_void" => PrimitiveType::Void,
|
||||
"c_char" => PrimitiveType::Char,
|
||||
"c_schar" => PrimitiveType::SChar,
|
||||
"c_uchar" => PrimitiveType::UChar,
|
||||
"c_float" => PrimitiveType::Float,
|
||||
"c_double" => PrimitiveType::Double,
|
||||
"ptrdiff_t" => PrimitiveType::PtrDiffT,
|
||||
"VaList" => PrimitiveType::VaList,
|
||||
"bool" => PrimitiveType::Bool,
|
||||
"char" => PrimitiveType::Char32,
|
||||
|
||||
"f32" => PrimitiveType::Float,
|
||||
"f64" => PrimitiveType::Double,
|
||||
|
||||
_ => {
|
||||
let (kind, signed) = match path {
|
||||
"c_short" => (IntKind::Short, true),
|
||||
"c_int" => (IntKind::Int, true),
|
||||
"c_long" => (IntKind::Long, true),
|
||||
"c_longlong" => (IntKind::LongLong, true),
|
||||
"ssize_t" => (IntKind::SizeT, true),
|
||||
"c_ushort" => (IntKind::Short, false),
|
||||
"c_uint" => (IntKind::Int, false),
|
||||
"c_ulong" => (IntKind::Long, false),
|
||||
"c_ulonglong" => (IntKind::LongLong, false),
|
||||
"size_t" => (IntKind::SizeT, false),
|
||||
|
||||
"isize" | "intptr_t" => (IntKind::Size, true),
|
||||
"usize" | "uintptr_t" => (IntKind::Size, false),
|
||||
|
||||
"u8" | "uint8_t" => (IntKind::B8, false),
|
||||
"u16" | "uint16_t" => (IntKind::B16, false),
|
||||
"u32" | "uint32_t" => (IntKind::B32, false),
|
||||
"u64" | "uint64_t" => (IntKind::B64, false),
|
||||
"i8" | "int8_t" => (IntKind::B8, true),
|
||||
"i16" | "int16_t" => (IntKind::B16, true),
|
||||
"i32" | "int32_t" => (IntKind::B32, true),
|
||||
"i64" | "int64_t" => (IntKind::B64, true),
|
||||
_ => return None,
|
||||
};
|
||||
PrimitiveType::Integer {
|
||||
zeroable: true,
|
||||
signed,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_repr_rust(&self) -> &'static str {
|
||||
match *self {
|
||||
PrimitiveType::Bool => "bool",
|
||||
PrimitiveType::Void => "c_void",
|
||||
PrimitiveType::Char => "c_char",
|
||||
PrimitiveType::SChar => "c_schar",
|
||||
PrimitiveType::UChar => "c_uchar",
|
||||
PrimitiveType::Char32 => "char",
|
||||
PrimitiveType::Integer {
|
||||
kind,
|
||||
signed,
|
||||
zeroable: _,
|
||||
} => match kind {
|
||||
IntKind::Short => {
|
||||
if signed {
|
||||
"c_short"
|
||||
} else {
|
||||
"c_ushort"
|
||||
}
|
||||
}
|
||||
IntKind::Int => {
|
||||
if signed {
|
||||
"c_int"
|
||||
} else {
|
||||
"c_uint"
|
||||
}
|
||||
}
|
||||
IntKind::Long => {
|
||||
if signed {
|
||||
"c_long"
|
||||
} else {
|
||||
"c_ulong"
|
||||
}
|
||||
}
|
||||
IntKind::LongLong => {
|
||||
if signed {
|
||||
"c_longlong"
|
||||
} else {
|
||||
"c_ulonglong"
|
||||
}
|
||||
}
|
||||
IntKind::SizeT => {
|
||||
if signed {
|
||||
"ssize_t"
|
||||
} else {
|
||||
"size_t"
|
||||
}
|
||||
}
|
||||
IntKind::Size => {
|
||||
if signed {
|
||||
"isize"
|
||||
} else {
|
||||
"usize"
|
||||
}
|
||||
}
|
||||
IntKind::B8 => {
|
||||
if signed {
|
||||
"i8"
|
||||
} else {
|
||||
"u8"
|
||||
}
|
||||
}
|
||||
IntKind::B16 => {
|
||||
if signed {
|
||||
"i16"
|
||||
} else {
|
||||
"u16"
|
||||
}
|
||||
}
|
||||
IntKind::B32 => {
|
||||
if signed {
|
||||
"i32"
|
||||
} else {
|
||||
"u32"
|
||||
}
|
||||
}
|
||||
IntKind::B64 => {
|
||||
if signed {
|
||||
"i64"
|
||||
} else {
|
||||
"u64"
|
||||
}
|
||||
}
|
||||
},
|
||||
PrimitiveType::Float => "f32",
|
||||
PrimitiveType::Double => "f64",
|
||||
PrimitiveType::PtrDiffT => "ptrdiff_t",
|
||||
PrimitiveType::VaList => "va_list",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_repr_c(&self, config: &Config) -> &'static str {
|
||||
match *self {
|
||||
PrimitiveType::Void => "void",
|
||||
PrimitiveType::Bool => "bool",
|
||||
PrimitiveType::Char => "char",
|
||||
PrimitiveType::SChar => "signed char",
|
||||
PrimitiveType::UChar => "unsigned char",
|
||||
// NOTE: It'd be nice to use a char32_t, but:
|
||||
//
|
||||
// * uchar.h is not present on mac (see #423).
|
||||
//
|
||||
// * char32_t isn't required to be compatible with Rust's char, as
|
||||
// the C++ spec only requires it to be the same size as
|
||||
// uint_least32_t, which is _not_ guaranteed to be 4-bytes.
|
||||
//
|
||||
PrimitiveType::Char32 => "uint32_t",
|
||||
PrimitiveType::Integer {
|
||||
kind,
|
||||
signed,
|
||||
zeroable: _,
|
||||
} => match kind {
|
||||
IntKind::Short => {
|
||||
if signed {
|
||||
"short"
|
||||
} else {
|
||||
"unsigned short"
|
||||
}
|
||||
}
|
||||
IntKind::Int => {
|
||||
if signed {
|
||||
"int"
|
||||
} else {
|
||||
"unsigned int"
|
||||
}
|
||||
}
|
||||
IntKind::Long => {
|
||||
if signed {
|
||||
"long"
|
||||
} else {
|
||||
"unsigned long"
|
||||
}
|
||||
}
|
||||
IntKind::LongLong => {
|
||||
if signed {
|
||||
"long long"
|
||||
} else {
|
||||
"unsigned long long"
|
||||
}
|
||||
}
|
||||
IntKind::SizeT => {
|
||||
if signed {
|
||||
"ssize_t"
|
||||
} else {
|
||||
"size_t"
|
||||
}
|
||||
}
|
||||
IntKind::Size => {
|
||||
if config.usize_is_size_t {
|
||||
if signed {
|
||||
"ptrdiff_t"
|
||||
} else {
|
||||
"size_t"
|
||||
}
|
||||
} else if signed {
|
||||
"intptr_t"
|
||||
} else {
|
||||
"uintptr_t"
|
||||
}
|
||||
}
|
||||
IntKind::B8 => {
|
||||
if signed {
|
||||
"int8_t"
|
||||
} else {
|
||||
"uint8_t"
|
||||
}
|
||||
}
|
||||
IntKind::B16 => {
|
||||
if signed {
|
||||
"int16_t"
|
||||
} else {
|
||||
"uint16_t"
|
||||
}
|
||||
}
|
||||
IntKind::B32 => {
|
||||
if signed {
|
||||
"int32_t"
|
||||
} else {
|
||||
"uint32_t"
|
||||
}
|
||||
}
|
||||
IntKind::B64 => {
|
||||
if signed {
|
||||
"int64_t"
|
||||
} else {
|
||||
"uint64_t"
|
||||
}
|
||||
}
|
||||
},
|
||||
PrimitiveType::Float => "float",
|
||||
PrimitiveType::Double => "double",
|
||||
PrimitiveType::PtrDiffT => "ptrdiff_t",
|
||||
PrimitiveType::VaList => "va_list",
|
||||
}
|
||||
}
|
||||
|
||||
fn can_cmp_order(&self) -> bool {
|
||||
match *self {
|
||||
PrimitiveType::Bool => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn can_cmp_eq(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// The `U` part of `[T; U]`
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum ArrayLength {
|
||||
Name(String),
|
||||
Value(String),
|
||||
}
|
||||
|
||||
impl ArrayLength {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
ArrayLength::Name(ref string) | ArrayLength::Value(ref string) => string,
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
if let ArrayLength::Name(ref mut name) = self {
|
||||
config.export.rename(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum Type {
|
||||
Ptr {
|
||||
ty: Box<Type>,
|
||||
is_const: bool,
|
||||
is_nullable: bool,
|
||||
// FIXME: This is a bit of a hack, this is only to get us to codegen
|
||||
// `T&` / `const T&`, but we should probably pass that down as an option
|
||||
// to code generation or something.
|
||||
is_ref: bool,
|
||||
},
|
||||
Path(GenericPath),
|
||||
Primitive(PrimitiveType),
|
||||
Array(Box<Type>, ArrayLength),
|
||||
FuncPtr {
|
||||
ret: Box<Type>,
|
||||
args: Vec<(Option<String>, Type)>,
|
||||
is_nullable: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn const_ref_to(ty: &Self) -> Self {
|
||||
Type::Ptr {
|
||||
ty: Box::new(ty.clone()),
|
||||
is_const: true,
|
||||
is_nullable: false,
|
||||
is_ref: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(ty: &syn::Type) -> Result<Option<Type>, String> {
|
||||
let converted = match *ty {
|
||||
syn::Type::Reference(ref reference) => {
|
||||
let converted = Type::load(&reference.elem)?;
|
||||
|
||||
let converted = match converted {
|
||||
Some(converted) => converted,
|
||||
None => Type::Primitive(PrimitiveType::Void),
|
||||
};
|
||||
|
||||
// TODO(emilio): we could make these use is_ref: true.
|
||||
let is_const = reference.mutability.is_none();
|
||||
Type::Ptr {
|
||||
ty: Box::new(converted),
|
||||
is_const,
|
||||
is_nullable: false,
|
||||
is_ref: false,
|
||||
}
|
||||
}
|
||||
syn::Type::Ptr(ref pointer) => {
|
||||
let converted = Type::load(&pointer.elem)?;
|
||||
|
||||
let converted = match converted {
|
||||
Some(converted) => converted,
|
||||
None => Type::Primitive(PrimitiveType::Void),
|
||||
};
|
||||
|
||||
let is_const = pointer.mutability.is_none();
|
||||
Type::Ptr {
|
||||
ty: Box::new(converted),
|
||||
is_const,
|
||||
is_nullable: true,
|
||||
is_ref: false,
|
||||
}
|
||||
}
|
||||
syn::Type::Path(ref path) => {
|
||||
let generic_path = GenericPath::load(&path.path)?;
|
||||
|
||||
if generic_path.name() == "PhantomData" || generic_path.name() == "PhantomPinned" {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Some(prim) = PrimitiveType::maybe(generic_path.name()) {
|
||||
if !generic_path.generics().is_empty() {
|
||||
return Err("Primitive has generics.".to_owned());
|
||||
}
|
||||
Type::Primitive(prim)
|
||||
} else {
|
||||
Type::Path(generic_path)
|
||||
}
|
||||
}
|
||||
syn::Type::Array(syn::TypeArray {
|
||||
ref elem,
|
||||
len: syn::Expr::Path(ref path),
|
||||
..
|
||||
}) => {
|
||||
let converted = Type::load(elem)?;
|
||||
|
||||
let converted = match converted {
|
||||
Some(converted) => converted,
|
||||
None => return Err("Cannot have an array of zero sized types.".to_owned()),
|
||||
};
|
||||
let generic_path = GenericPath::load(&path.path)?;
|
||||
let len = ArrayLength::Name(generic_path.export_name().to_owned());
|
||||
Type::Array(Box::new(converted), len)
|
||||
}
|
||||
syn::Type::Array(syn::TypeArray {
|
||||
ref elem,
|
||||
len:
|
||||
syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Int(ref len),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) => {
|
||||
let converted = Type::load(elem)?;
|
||||
|
||||
let converted = match converted {
|
||||
Some(converted) => converted,
|
||||
None => return Err("Cannot have an array of zero sized types.".to_owned()),
|
||||
};
|
||||
|
||||
let len = ArrayLength::Value(len.base10_digits().to_string());
|
||||
// panic!("panic -> value: {:?}", len);
|
||||
Type::Array(Box::new(converted), len)
|
||||
}
|
||||
syn::Type::BareFn(ref function) => {
|
||||
let mut wildcard_counter = 0;
|
||||
let args = function.inputs.iter().try_skip_map(|x| {
|
||||
Type::load(&x.ty).map(|opt_ty| {
|
||||
opt_ty.map(|ty| {
|
||||
(
|
||||
x.name.as_ref().map(|(ref ident, _)| {
|
||||
if ident == "_" {
|
||||
wildcard_counter += 1;
|
||||
if wildcard_counter == 1 {
|
||||
"_".to_owned()
|
||||
} else {
|
||||
format!("_{}", wildcard_counter - 1)
|
||||
}
|
||||
} else {
|
||||
ident.to_string()
|
||||
}
|
||||
}),
|
||||
ty,
|
||||
)
|
||||
})
|
||||
})
|
||||
})?;
|
||||
let ret = match function.output {
|
||||
syn::ReturnType::Default => Type::Primitive(PrimitiveType::Void),
|
||||
syn::ReturnType::Type(_, ref ty) => {
|
||||
if let Some(x) = Type::load(ty)? {
|
||||
x
|
||||
} else {
|
||||
Type::Primitive(PrimitiveType::Void)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Type::FuncPtr {
|
||||
ret: Box::new(ret),
|
||||
args,
|
||||
is_nullable: false,
|
||||
}
|
||||
}
|
||||
syn::Type::Tuple(ref tuple) => {
|
||||
if tuple.elems.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
return Err("Tuples are not supported types.".to_owned());
|
||||
}
|
||||
_ => return Err(format!("Unsupported type: {:?}", ty)),
|
||||
};
|
||||
|
||||
Ok(Some(converted))
|
||||
}
|
||||
|
||||
pub fn is_primitive_or_ptr_primitive(&self) -> bool {
|
||||
match *self {
|
||||
Type::Primitive(..) => true,
|
||||
Type::Ptr { ref ty, .. } => match ty.as_ref() {
|
||||
Type::Primitive(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_zeroable(&self) -> Option<Self> {
|
||||
let (kind, signed) = match *self {
|
||||
Type::Primitive(PrimitiveType::Integer {
|
||||
zeroable: false,
|
||||
kind,
|
||||
signed,
|
||||
}) => (kind, signed),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Type::Primitive(PrimitiveType::Integer {
|
||||
kind,
|
||||
signed,
|
||||
zeroable: true,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn make_nullable(&self) -> Option<Self> {
|
||||
match *self {
|
||||
Type::Ptr {
|
||||
ref ty,
|
||||
is_const,
|
||||
is_ref,
|
||||
is_nullable: false,
|
||||
} => Some(Type::Ptr {
|
||||
ty: ty.clone(),
|
||||
is_const,
|
||||
is_ref,
|
||||
is_nullable: true,
|
||||
}),
|
||||
Type::FuncPtr {
|
||||
ref ret,
|
||||
ref args,
|
||||
is_nullable: false,
|
||||
} => Some(Type::FuncPtr {
|
||||
ret: ret.clone(),
|
||||
args: args.clone(),
|
||||
is_nullable: true,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn nonzero_to_primitive(&self) -> Option<Self> {
|
||||
let path = match *self {
|
||||
Type::Path(ref p) => p,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if !path.generics().is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let name = path.name();
|
||||
if !name.starts_with("NonZero") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (kind, signed) = match path.name() {
|
||||
"NonZeroU8" => (IntKind::B8, false),
|
||||
"NonZeroU16" => (IntKind::B16, false),
|
||||
"NonZeroU32" => (IntKind::B32, false),
|
||||
"NonZeroU64" => (IntKind::B64, false),
|
||||
"NonZeroUSize" => (IntKind::Size, false),
|
||||
"NonZeroI8" => (IntKind::B8, true),
|
||||
"NonZeroI16" => (IntKind::B16, true),
|
||||
"NonZeroI32" => (IntKind::B32, true),
|
||||
"NonZeroI64" => (IntKind::B64, true),
|
||||
"NonZeroISize" => (IntKind::Size, true),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Type::Primitive(PrimitiveType::Integer {
|
||||
zeroable: false,
|
||||
signed,
|
||||
kind,
|
||||
}))
|
||||
}
|
||||
|
||||
fn simplified_type(&self, config: &Config) -> Option<Self> {
|
||||
let path = match *self {
|
||||
Type::Path(ref p) => p,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if path.generics().is_empty() {
|
||||
return self.nonzero_to_primitive();
|
||||
}
|
||||
|
||||
if path.generics().len() != 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let unsimplified_generic = &path.generics()[0];
|
||||
let generic = match unsimplified_generic.simplified_type(config) {
|
||||
Some(generic) => Cow::Owned(generic),
|
||||
None => Cow::Borrowed(unsimplified_generic),
|
||||
};
|
||||
match path.name() {
|
||||
"Option" => {
|
||||
if let Some(nullable) = generic.make_nullable() {
|
||||
return Some(nullable);
|
||||
}
|
||||
if let Some(zeroable) = generic.make_zeroable() {
|
||||
return Some(zeroable);
|
||||
}
|
||||
None
|
||||
}
|
||||
"NonNull" => Some(Type::Ptr {
|
||||
ty: Box::new(generic.into_owned()),
|
||||
is_const: false,
|
||||
is_nullable: false,
|
||||
is_ref: false,
|
||||
}),
|
||||
"Box" if config.language != Language::Cxx => Some(Type::Ptr {
|
||||
ty: Box::new(generic.into_owned()),
|
||||
is_const: false,
|
||||
is_nullable: false,
|
||||
is_ref: false,
|
||||
}),
|
||||
"Cell" => Some(generic.into_owned()),
|
||||
"ManuallyDrop" | "MaybeUninit" | "Pin" if config.language != Language::Cxx => {
|
||||
Some(generic.into_owned())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
self.visit_types(|ty| ty.simplify_standard_types(config));
|
||||
if let Some(ty) = self.simplified_type(config) {
|
||||
*self = ty;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_self_with(&mut self, self_ty: &Path) {
|
||||
if let Type::Path(ref mut generic_path) = *self {
|
||||
generic_path.replace_self_with(self_ty);
|
||||
}
|
||||
self.visit_types(|ty| ty.replace_self_with(self_ty))
|
||||
}
|
||||
|
||||
fn visit_types(&mut self, mut visitor: impl FnMut(&mut Type)) {
|
||||
match *self {
|
||||
Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty),
|
||||
Type::Path(ref mut path) => {
|
||||
for generic in path.generics_mut() {
|
||||
visitor(generic);
|
||||
}
|
||||
}
|
||||
Type::Primitive(..) => {}
|
||||
Type::FuncPtr {
|
||||
ref mut ret,
|
||||
ref mut args,
|
||||
..
|
||||
} => {
|
||||
visitor(ret);
|
||||
for arg in args {
|
||||
visitor(&mut arg.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_root_path(&self) -> Option<Path> {
|
||||
let mut current = self;
|
||||
loop {
|
||||
match *current {
|
||||
Type::Ptr { ref ty, .. } => current = ty,
|
||||
Type::Path(ref generic) => {
|
||||
return Some(generic.path().clone());
|
||||
}
|
||||
Type::Primitive(..) => {
|
||||
return None;
|
||||
}
|
||||
Type::Array(..) => {
|
||||
return None;
|
||||
}
|
||||
Type::FuncPtr { .. } => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn specialize(&self, mappings: &[(&Path, &Type)]) -> Type {
|
||||
match *self {
|
||||
Type::Ptr {
|
||||
ref ty,
|
||||
is_const,
|
||||
is_nullable,
|
||||
is_ref,
|
||||
} => Type::Ptr {
|
||||
ty: Box::new(ty.specialize(mappings)),
|
||||
is_const,
|
||||
is_nullable,
|
||||
is_ref,
|
||||
},
|
||||
Type::Path(ref generic_path) => {
|
||||
for &(param, value) in mappings {
|
||||
if generic_path.path() == param {
|
||||
return value.clone();
|
||||
}
|
||||
}
|
||||
|
||||
let specialized = GenericPath::new(
|
||||
generic_path.path().clone(),
|
||||
generic_path
|
||||
.generics()
|
||||
.iter()
|
||||
.map(|x| x.specialize(mappings))
|
||||
.collect(),
|
||||
);
|
||||
Type::Path(specialized)
|
||||
}
|
||||
Type::Primitive(ref primitive) => Type::Primitive(primitive.clone()),
|
||||
Type::Array(ref ty, ref constant) => {
|
||||
Type::Array(Box::new(ty.specialize(mappings)), constant.clone())
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref ret,
|
||||
ref args,
|
||||
is_nullable,
|
||||
} => Type::FuncPtr {
|
||||
ret: Box::new(ret.specialize(mappings)),
|
||||
args: args
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|(name, ty)| (name, ty.specialize(mappings)))
|
||||
.collect(),
|
||||
is_nullable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_dependencies_ignoring_generics(
|
||||
&self,
|
||||
generic_params: &GenericParams,
|
||||
library: &Library,
|
||||
out: &mut Dependencies,
|
||||
) {
|
||||
match *self {
|
||||
Type::Ptr { ref ty, .. } => {
|
||||
ty.add_dependencies_ignoring_generics(generic_params, library, out);
|
||||
}
|
||||
Type::Path(ref generic) => {
|
||||
for generic_value in generic.generics() {
|
||||
generic_value.add_dependencies_ignoring_generics(generic_params, library, out);
|
||||
}
|
||||
let path = generic.path();
|
||||
if !generic_params.contains(path) {
|
||||
if let Some(items) = library.get_items(path) {
|
||||
if !out.items.contains(path) {
|
||||
out.items.insert(path.clone());
|
||||
|
||||
for item in &items {
|
||||
item.deref().add_dependencies(library, out);
|
||||
}
|
||||
for item in items {
|
||||
out.order.push(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"Can't find {}. This usually means that this type was incompatible or \
|
||||
not found.",
|
||||
path
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Array(ref ty, _) => {
|
||||
ty.add_dependencies_ignoring_generics(generic_params, library, out);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref ret, ref args, ..
|
||||
} => {
|
||||
ret.add_dependencies_ignoring_generics(generic_params, library, out);
|
||||
for (_, ref arg) in args {
|
||||
arg.add_dependencies_ignoring_generics(generic_params, library, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.add_dependencies_ignoring_generics(&GenericParams::default(), library, out)
|
||||
}
|
||||
|
||||
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
|
||||
match *self {
|
||||
Type::Ptr { ref ty, .. } => {
|
||||
ty.add_monomorphs(library, out);
|
||||
}
|
||||
Type::Path(ref generic) => {
|
||||
if generic.generics().is_empty() || out.contains(generic) {
|
||||
return;
|
||||
}
|
||||
let path = generic.path();
|
||||
if let Some(items) = library.get_items(path) {
|
||||
for item in items {
|
||||
item.deref()
|
||||
.instantiate_monomorph(generic.generics(), library, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Array(ref ty, _) => {
|
||||
ty.add_monomorphs(library, out);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref ret, ref args, ..
|
||||
} => {
|
||||
ret.add_monomorphs(library, out);
|
||||
for (_, ref arg) in args {
|
||||
arg.add_monomorphs(library, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
|
||||
match *self {
|
||||
Type::Ptr { ref mut ty, .. } => {
|
||||
ty.rename_for_config(config, generic_params);
|
||||
}
|
||||
Type::Path(ref mut ty) => {
|
||||
ty.rename_for_config(config, generic_params);
|
||||
}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Array(ref mut ty, ref mut len) => {
|
||||
ty.rename_for_config(config, generic_params);
|
||||
len.rename_for_config(config);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref mut ret,
|
||||
ref mut args,
|
||||
..
|
||||
} => {
|
||||
ret.rename_for_config(config, generic_params);
|
||||
for (_, arg) in args {
|
||||
arg.rename_for_config(config, generic_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
match *self {
|
||||
Type::Ptr { ref mut ty, .. } => {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
Type::Path(ref mut generic_path) => {
|
||||
generic_path.resolve_declaration_types(resolver);
|
||||
}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Array(ref mut ty, _) => {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref mut ret,
|
||||
ref mut args,
|
||||
..
|
||||
} => {
|
||||
ret.resolve_declaration_types(resolver);
|
||||
for (_, ref mut arg) in args {
|
||||
arg.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
match *self {
|
||||
Type::Ptr { ref mut ty, .. } => {
|
||||
ty.mangle_paths(monomorphs);
|
||||
}
|
||||
Type::Path(ref mut generic_path) => {
|
||||
if generic_path.generics().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(mangled_path) = monomorphs.mangle_path(generic_path) {
|
||||
*generic_path = GenericPath::new(mangled_path.clone(), vec![]);
|
||||
} else {
|
||||
warn!(
|
||||
"Cannot find a mangling for generic path {:?}. This usually means that a \
|
||||
type referenced by this generic was incompatible or not found.",
|
||||
generic_path
|
||||
);
|
||||
}
|
||||
}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Array(ref mut ty, _) => {
|
||||
ty.mangle_paths(monomorphs);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref mut ret,
|
||||
ref mut args,
|
||||
..
|
||||
} => {
|
||||
ret.mangle_paths(monomorphs);
|
||||
for (_, ref mut arg) in args {
|
||||
arg.mangle_paths(monomorphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_cmp_order(&self) -> bool {
|
||||
match *self {
|
||||
// FIXME: Shouldn't this look at ty.can_cmp_order() as well?
|
||||
Type::Ptr { is_ref, .. } => !is_ref,
|
||||
Type::Path(..) => true,
|
||||
Type::Primitive(ref p) => p.can_cmp_order(),
|
||||
Type::Array(..) => false,
|
||||
Type::FuncPtr { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_cmp_eq(&self) -> bool {
|
||||
match *self {
|
||||
Type::Ptr { ref ty, is_ref, .. } => !is_ref || ty.can_cmp_eq(),
|
||||
Type::Path(..) => true,
|
||||
Type::Primitive(ref p) => p.can_cmp_eq(),
|
||||
Type::Array(..) => false,
|
||||
Type::FuncPtr { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for String {
|
||||
fn write<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) {
|
||||
write!(out, "{}", self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Type {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
cdecl::write_type(out, self, config);
|
||||
}
|
||||
}
|
||||
223
zeroidc/vendor/cbindgen/src/bindgen/ir/typedef.rs
vendored
Normal file
223
zeroidc/vendor/cbindgen/src/bindgen/ir/typedef.rs
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Config, Language};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer,
|
||||
Path, ToCondition, Type,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::mangle;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
/// A type alias that is represented as a C typedef
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Typedef {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub generic_params: GenericParams,
|
||||
pub aliased: Type,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
}
|
||||
|
||||
impl Typedef {
|
||||
pub fn load(item: &syn::ItemType, mod_cfg: Option<&Cfg>) -> Result<Typedef, String> {
|
||||
if let Some(x) = Type::load(&item.ty)? {
|
||||
let path = Path::new(item.ident.to_string());
|
||||
Ok(Typedef::new(
|
||||
path,
|
||||
GenericParams::new(&item.generics),
|
||||
x,
|
||||
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
|
||||
AnnotationSet::load(&item.attrs)?,
|
||||
Documentation::load(&item.attrs),
|
||||
))
|
||||
} else {
|
||||
Err("Cannot have a typedef of a zero sized type.".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
path: Path,
|
||||
generic_params: GenericParams,
|
||||
aliased: Type,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
generic_params,
|
||||
aliased,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
self.aliased.simplify_standard_types(config);
|
||||
}
|
||||
|
||||
pub fn transfer_annotations(&mut self, out: &mut HashMap<Path, AnnotationSet>) {
|
||||
if self.annotations.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(alias_path) = self.aliased.get_root_path() {
|
||||
if out.contains_key(&alias_path) {
|
||||
warn!(
|
||||
"Multiple typedef's with annotations for {}. Ignoring annotations from {}.",
|
||||
alias_path, self.path
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
out.insert(alias_path, self.annotations.clone());
|
||||
self.annotations = AnnotationSet::new();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_generic(&self) -> bool {
|
||||
self.generic_params.len() > 0
|
||||
}
|
||||
|
||||
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
|
||||
// Generic structs can instantiate monomorphs only once they've been
|
||||
// instantiated. See `instantiate_monomorph` for more details.
|
||||
if self.is_generic() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.aliased.add_monomorphs(library, out);
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
self.aliased.mangle_paths(monomorphs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Typedef {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Typedef(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.export_name);
|
||||
self.aliased.rename_for_config(config, &self.generic_params);
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_none(&self.path);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.aliased.resolve_declaration_types(resolver);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.aliased
|
||||
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
|
||||
}
|
||||
|
||||
fn instantiate_monomorph(
|
||||
&self,
|
||||
generic_values: &[Type],
|
||||
library: &Library,
|
||||
out: &mut Monomorphs,
|
||||
) {
|
||||
assert!(
|
||||
self.generic_params.len() > 0,
|
||||
"{} is not generic",
|
||||
self.path
|
||||
);
|
||||
assert!(
|
||||
self.generic_params.len() == generic_values.len(),
|
||||
"{} has {} params but is being instantiated with {} values",
|
||||
self.path,
|
||||
self.generic_params.len(),
|
||||
generic_values.len(),
|
||||
);
|
||||
|
||||
let mappings = self
|
||||
.generic_params
|
||||
.iter()
|
||||
.zip(generic_values.iter())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mangled_path = mangle::mangle_path(
|
||||
&self.path,
|
||||
generic_values,
|
||||
&library.get_config().export.mangle,
|
||||
);
|
||||
|
||||
let monomorph = Typedef::new(
|
||||
mangled_path,
|
||||
GenericParams::default(),
|
||||
self.aliased.specialize(&mappings),
|
||||
self.cfg.clone(),
|
||||
self.annotations.clone(),
|
||||
self.documentation.clone(),
|
||||
);
|
||||
|
||||
out.insert_typedef(library, self, monomorph, generic_values.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Typedef {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
let condition = self.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
|
||||
match config.language {
|
||||
Language::Cxx => {
|
||||
write!(out, "using {} = ", self.export_name());
|
||||
self.aliased.write(config, out);
|
||||
}
|
||||
Language::C | Language::Cython => {
|
||||
write!(out, "{} ", config.language.typedef());
|
||||
Field::from_name_and_type(self.export_name().to_owned(), self.aliased.clone())
|
||||
.write(config, out);
|
||||
}
|
||||
}
|
||||
|
||||
out.write(";");
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
}
|
||||
351
zeroidc/vendor/cbindgen/src/bindgen/ir/union.rs
vendored
Normal file
351
zeroidc/vendor/cbindgen/src/bindgen/ir/union.rs
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Config, Language, LayoutConfig};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer,
|
||||
Path, Repr, ReprAlign, ReprStyle, ToCondition, Type,
|
||||
};
|
||||
use crate::bindgen::library::Library;
|
||||
use crate::bindgen::mangle;
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::rename::{IdentifierType, RenameRule};
|
||||
use crate::bindgen::utilities::IterHelpers;
|
||||
use crate::bindgen::writer::{ListType, Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Union {
|
||||
pub path: Path,
|
||||
pub export_name: String,
|
||||
pub generic_params: GenericParams,
|
||||
pub fields: Vec<Field>,
|
||||
pub tuple_union: bool,
|
||||
pub alignment: Option<ReprAlign>,
|
||||
pub cfg: Option<Cfg>,
|
||||
pub annotations: AnnotationSet,
|
||||
pub documentation: Documentation,
|
||||
}
|
||||
|
||||
impl Union {
|
||||
pub fn load(
|
||||
layout_config: &LayoutConfig,
|
||||
item: &syn::ItemUnion,
|
||||
mod_cfg: Option<&Cfg>,
|
||||
) -> Result<Union, String> {
|
||||
let repr = Repr::load(&item.attrs)?;
|
||||
if repr.style != ReprStyle::C {
|
||||
return Err("Union is not marked #[repr(C)].".to_owned());
|
||||
}
|
||||
|
||||
// Ensure we can safely represent the union given the configuration.
|
||||
if let Some(align) = repr.align {
|
||||
layout_config.ensure_safe_to_represent(&align)?;
|
||||
}
|
||||
|
||||
let path = Path::new(item.ident.to_string());
|
||||
|
||||
let (fields, tuple_union) = {
|
||||
let out = item
|
||||
.fields
|
||||
.named
|
||||
.iter()
|
||||
.try_skip_map(|field| Field::load(field, &path))?;
|
||||
(out, false)
|
||||
};
|
||||
|
||||
Ok(Union::new(
|
||||
path,
|
||||
GenericParams::new(&item.generics),
|
||||
fields,
|
||||
repr.align,
|
||||
tuple_union,
|
||||
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
|
||||
AnnotationSet::load(&item.attrs)?,
|
||||
Documentation::load(&item.attrs),
|
||||
))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
path: Path,
|
||||
generic_params: GenericParams,
|
||||
fields: Vec<Field>,
|
||||
alignment: Option<ReprAlign>,
|
||||
tuple_union: bool,
|
||||
cfg: Option<Cfg>,
|
||||
annotations: AnnotationSet,
|
||||
documentation: Documentation,
|
||||
) -> Self {
|
||||
let export_name = path.name().to_owned();
|
||||
Self {
|
||||
path,
|
||||
export_name,
|
||||
generic_params,
|
||||
fields,
|
||||
tuple_union,
|
||||
alignment,
|
||||
cfg,
|
||||
annotations,
|
||||
documentation,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simplify_standard_types(&mut self, config: &Config) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.simplify_standard_types(config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_generic(&self) -> bool {
|
||||
self.generic_params.len() > 0
|
||||
}
|
||||
|
||||
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
|
||||
// Generic unions can instantiate monomorphs only once they've been
|
||||
// instantiated. See `instantiate_monomorph` for more details.
|
||||
if self.is_generic() {
|
||||
return;
|
||||
}
|
||||
|
||||
for field in &self.fields {
|
||||
field.ty.add_monomorphs(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.mangle_paths(monomorphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Union {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn export_name(&self) -> &str {
|
||||
&self.export_name
|
||||
}
|
||||
|
||||
fn cfg(&self) -> Option<&Cfg> {
|
||||
self.cfg.as_ref()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &AnnotationSet {
|
||||
&self.annotations
|
||||
}
|
||||
|
||||
fn annotations_mut(&mut self) -> &mut AnnotationSet {
|
||||
&mut self.annotations
|
||||
}
|
||||
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Union(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_union(&self.path);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
for field in &mut self.fields {
|
||||
field.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.export_name);
|
||||
for field in &mut self.fields {
|
||||
field.ty.rename_for_config(config, &self.generic_params);
|
||||
}
|
||||
|
||||
let rules = self
|
||||
.annotations
|
||||
.parse_atom::<RenameRule>("rename-all")
|
||||
.unwrap_or(config.structure.rename_fields);
|
||||
|
||||
if let Some(o) = self.annotations.list("field-names") {
|
||||
let mut overriden_fields = Vec::new();
|
||||
|
||||
for (i, field) in self.fields.iter().enumerate() {
|
||||
if i >= o.len() {
|
||||
overriden_fields.push(field.clone());
|
||||
} else {
|
||||
overriden_fields.push(Field {
|
||||
name: o[i].clone(),
|
||||
ty: field.ty.clone(),
|
||||
cfg: field.cfg.clone(),
|
||||
annotations: field.annotations.clone(),
|
||||
documentation: field.documentation.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.fields = overriden_fields;
|
||||
} else if let Some(r) = rules.not_none() {
|
||||
self.fields = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| Field {
|
||||
name: r
|
||||
.apply(&field.name, IdentifierType::StructMember)
|
||||
.into_owned(),
|
||||
ty: field.ty.clone(),
|
||||
cfg: field.cfg.clone(),
|
||||
annotations: field.annotations.clone(),
|
||||
documentation: field.documentation.clone(),
|
||||
})
|
||||
.collect();
|
||||
} else if self.tuple_union {
|
||||
// If we don't have any rules for a tuple union, prefix them with
|
||||
// an underscore so it still compiles
|
||||
for field in &mut self.fields {
|
||||
field.name.insert(0, '_');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
for field in &self.fields {
|
||||
field
|
||||
.ty
|
||||
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
|
||||
}
|
||||
}
|
||||
|
||||
fn instantiate_monomorph(
|
||||
&self,
|
||||
generic_values: &[Type],
|
||||
library: &Library,
|
||||
out: &mut Monomorphs,
|
||||
) {
|
||||
assert!(
|
||||
self.generic_params.len() > 0,
|
||||
"{} is not generic",
|
||||
self.path
|
||||
);
|
||||
assert!(
|
||||
self.generic_params.len() == generic_values.len(),
|
||||
"{} has {} params but is being instantiated with {} values",
|
||||
self.path,
|
||||
self.generic_params.len(),
|
||||
generic_values.len(),
|
||||
);
|
||||
|
||||
let mappings = self
|
||||
.generic_params
|
||||
.iter()
|
||||
.zip(generic_values.iter())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mangled_path = mangle::mangle_path(
|
||||
&self.path,
|
||||
generic_values,
|
||||
&library.get_config().export.mangle,
|
||||
);
|
||||
|
||||
let monomorph = Union::new(
|
||||
mangled_path,
|
||||
GenericParams::default(),
|
||||
self.fields
|
||||
.iter()
|
||||
.map(|field| Field {
|
||||
name: field.name.clone(),
|
||||
ty: field.ty.specialize(&mappings),
|
||||
cfg: field.cfg.clone(),
|
||||
annotations: field.annotations.clone(),
|
||||
documentation: field.documentation.clone(),
|
||||
})
|
||||
.collect(),
|
||||
self.alignment,
|
||||
self.tuple_union,
|
||||
self.cfg.clone(),
|
||||
self.annotations.clone(),
|
||||
self.documentation.clone(),
|
||||
);
|
||||
|
||||
out.insert_union(library, self, monomorph, generic_values.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Union {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
let condition = self.cfg.to_condition(config);
|
||||
condition.write_before(config, out);
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
|
||||
// The following results in
|
||||
// C++ or C with Tag as style:
|
||||
// union Name {
|
||||
// C with Type only style:
|
||||
// typedef union {
|
||||
// C with Both as style:
|
||||
// typedef union Name {
|
||||
match config.language {
|
||||
Language::C if config.style.generate_typedef() => out.write("typedef "),
|
||||
Language::C | Language::Cxx => {}
|
||||
Language::Cython => out.write(config.style.cython_def()),
|
||||
}
|
||||
|
||||
out.write("union");
|
||||
|
||||
// Cython supports `packed` on structs (see comments there), but not on unions.
|
||||
if config.language != Language::Cython {
|
||||
if let Some(align) = self.alignment {
|
||||
match align {
|
||||
ReprAlign::Packed => {
|
||||
if let Some(ref anno) = config.layout.packed {
|
||||
write!(out, " {}", anno);
|
||||
}
|
||||
}
|
||||
ReprAlign::Align(n) => {
|
||||
if let Some(ref anno) = config.layout.aligned_n {
|
||||
write!(out, " {}({})", anno, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if config.language != Language::C || config.style.generate_tag() {
|
||||
write!(out, " {}", self.export_name);
|
||||
}
|
||||
|
||||
out.open_brace();
|
||||
|
||||
// Emit the pre_body section, if relevant
|
||||
if let Some(body) = config.export.pre_body(&self.path) {
|
||||
out.write_raw_block(body);
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
out.write_vertical_source_list(&self.fields, ListType::Cap(";"));
|
||||
if config.language == Language::Cython && self.fields.is_empty() {
|
||||
out.write("pass");
|
||||
}
|
||||
|
||||
// Emit the post_body section, if relevant
|
||||
if let Some(body) = config.export.post_body(&self.path) {
|
||||
out.new_line();
|
||||
out.write_raw_block(body);
|
||||
}
|
||||
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.export_name);
|
||||
} else {
|
||||
out.close_brace(true);
|
||||
}
|
||||
|
||||
condition.write_after(config, out);
|
||||
}
|
||||
}
|
||||
436
zeroidc/vendor/cbindgen/src/bindgen/library.rs
vendored
Normal file
436
zeroidc/vendor/cbindgen/src/bindgen/library.rs
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::HashMap;
|
||||
|
||||
use crate::bindgen::bindings::Bindings;
|
||||
use crate::bindgen::config::{Config, Language, SortKey};
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use crate::bindgen::dependencies::Dependencies;
|
||||
use crate::bindgen::error::Error;
|
||||
use crate::bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap};
|
||||
use crate::bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union};
|
||||
use crate::bindgen::monomorph::Monomorphs;
|
||||
use crate::bindgen::ItemType;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Library {
|
||||
config: Config,
|
||||
constants: ItemMap<Constant>,
|
||||
globals: ItemMap<Static>,
|
||||
enums: ItemMap<Enum>,
|
||||
structs: ItemMap<Struct>,
|
||||
unions: ItemMap<Union>,
|
||||
opaque_items: ItemMap<OpaqueItem>,
|
||||
typedefs: ItemMap<Typedef>,
|
||||
functions: Vec<Function>,
|
||||
}
|
||||
|
||||
impl Library {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
config: Config,
|
||||
constants: ItemMap<Constant>,
|
||||
globals: ItemMap<Static>,
|
||||
enums: ItemMap<Enum>,
|
||||
structs: ItemMap<Struct>,
|
||||
unions: ItemMap<Union>,
|
||||
opaque_items: ItemMap<OpaqueItem>,
|
||||
typedefs: ItemMap<Typedef>,
|
||||
functions: Vec<Function>,
|
||||
) -> Library {
|
||||
Library {
|
||||
config,
|
||||
constants,
|
||||
globals,
|
||||
enums,
|
||||
structs,
|
||||
unions,
|
||||
opaque_items,
|
||||
typedefs,
|
||||
functions,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(mut self) -> Result<Bindings, Error> {
|
||||
self.transfer_annotations();
|
||||
self.simplify_standard_types();
|
||||
|
||||
match self.config.function.sort_by.unwrap_or(self.config.sort_by) {
|
||||
SortKey::Name => self.functions.sort_by(|x, y| x.path.cmp(&y.path)),
|
||||
SortKey::None => { /* keep input order */ }
|
||||
}
|
||||
|
||||
if self.config.language != Language::Cxx {
|
||||
self.instantiate_monomorphs();
|
||||
}
|
||||
self.remove_excluded();
|
||||
if self.config.language == Language::C {
|
||||
self.resolve_declaration_types();
|
||||
}
|
||||
|
||||
self.rename_items();
|
||||
|
||||
let mut dependencies = Dependencies::new();
|
||||
|
||||
for function in &self.functions {
|
||||
function.add_dependencies(&self, &mut dependencies);
|
||||
}
|
||||
self.globals.for_all_items(|global| {
|
||||
global.add_dependencies(&self, &mut dependencies);
|
||||
});
|
||||
self.constants.for_all_items(|constant| {
|
||||
constant.add_dependencies(&self, &mut dependencies);
|
||||
});
|
||||
for name in &self.config.export.include {
|
||||
let path = Path::new(name.clone());
|
||||
if let Some(items) = self.get_items(&path) {
|
||||
if dependencies.items.insert(path) {
|
||||
for item in &items {
|
||||
item.deref().add_dependencies(&self, &mut dependencies);
|
||||
}
|
||||
for item in items {
|
||||
dependencies.order.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies.sort();
|
||||
|
||||
let items = dependencies.order;
|
||||
let constants = if self.config.export.should_generate(ItemType::Constants) {
|
||||
let mut constants = self.constants.to_vec();
|
||||
match self.config.constant.sort_by.unwrap_or(self.config.sort_by) {
|
||||
SortKey::Name => constants.sort_by(|x, y| x.path.cmp(&y.path)),
|
||||
SortKey::None => { /* keep input order */ }
|
||||
}
|
||||
constants
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let globals = if self.config.export.should_generate(ItemType::Globals) {
|
||||
let mut globals = self.globals.to_vec();
|
||||
match self.config.constant.sort_by.unwrap_or(self.config.sort_by) {
|
||||
SortKey::Name => globals.sort_by(|x, y| x.path.cmp(&y.path)),
|
||||
SortKey::None => { /* keep input order */ }
|
||||
}
|
||||
globals
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let functions = if self.config.export.should_generate(ItemType::Functions) {
|
||||
self.functions
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
Ok(Bindings::new(
|
||||
self.config,
|
||||
self.structs,
|
||||
constants,
|
||||
globals,
|
||||
items,
|
||||
functions,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_items(&self, p: &Path) -> Option<Vec<ItemContainer>> {
|
||||
macro_rules! find {
|
||||
($field:ident, $kind:ident) => {
|
||||
if self.config.export.should_generate(ItemType::$kind) {
|
||||
if let Some(x) = self.$field.get_items(p) {
|
||||
return Some(x);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
find!(enums, Enums);
|
||||
find!(structs, Structs);
|
||||
find!(unions, Unions);
|
||||
find!(opaque_items, OpaqueItems);
|
||||
find!(typedefs, Typedefs);
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
fn remove_excluded(&mut self) {
|
||||
let config = &self.config;
|
||||
// FIXME: interpret `config.export.exclude` as `Path`s.
|
||||
self.functions
|
||||
.retain(|x| !config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.enums
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.structs
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.unions
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.opaque_items
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.typedefs
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.globals
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
self.constants
|
||||
.filter(|x| config.export.exclude.iter().any(|y| y == x.path().name()));
|
||||
}
|
||||
|
||||
fn transfer_annotations(&mut self) {
|
||||
let mut annotations = HashMap::new();
|
||||
|
||||
self.typedefs.for_all_items_mut(|x| {
|
||||
x.transfer_annotations(&mut annotations);
|
||||
});
|
||||
|
||||
for (alias_path, annotations) in annotations {
|
||||
// TODO
|
||||
let mut transferred = false;
|
||||
|
||||
self.enums.for_items_mut(&alias_path, |x| {
|
||||
if x.annotations().is_empty() {
|
||||
*x.annotations_mut() = annotations.clone();
|
||||
transferred = true;
|
||||
} else {
|
||||
warn!(
|
||||
"Can't transfer annotations from typedef to alias ({}) \
|
||||
that already has annotations.",
|
||||
alias_path
|
||||
);
|
||||
}
|
||||
});
|
||||
if transferred {
|
||||
continue;
|
||||
}
|
||||
self.structs.for_items_mut(&alias_path, |x| {
|
||||
if x.annotations().is_empty() {
|
||||
*x.annotations_mut() = annotations.clone();
|
||||
transferred = true;
|
||||
} else {
|
||||
warn!(
|
||||
"Can't transfer annotations from typedef to alias ({}) \
|
||||
that already has annotations.",
|
||||
alias_path
|
||||
);
|
||||
}
|
||||
});
|
||||
if transferred {
|
||||
continue;
|
||||
}
|
||||
self.unions.for_items_mut(&alias_path, |x| {
|
||||
if x.annotations().is_empty() {
|
||||
*x.annotations_mut() = annotations.clone();
|
||||
transferred = true;
|
||||
} else {
|
||||
warn!(
|
||||
"Can't transfer annotations from typedef to alias ({}) \
|
||||
that already has annotations.",
|
||||
alias_path
|
||||
);
|
||||
}
|
||||
});
|
||||
if transferred {
|
||||
continue;
|
||||
}
|
||||
self.opaque_items.for_items_mut(&alias_path, |x| {
|
||||
if x.annotations().is_empty() {
|
||||
*x.annotations_mut() = annotations.clone();
|
||||
transferred = true;
|
||||
} else {
|
||||
warn!(
|
||||
"Can't transfer annotations from typedef to alias ({}) \
|
||||
that already has annotations.",
|
||||
alias_path
|
||||
);
|
||||
}
|
||||
});
|
||||
if transferred {
|
||||
continue;
|
||||
}
|
||||
self.typedefs.for_items_mut(&alias_path, |x| {
|
||||
if x.annotations().is_empty() {
|
||||
*x.annotations_mut() = annotations.clone();
|
||||
transferred = true;
|
||||
} else {
|
||||
warn!(
|
||||
"Can't transfer annotations from typedef to alias ({}) \
|
||||
that already has annotations.",
|
||||
alias_path
|
||||
);
|
||||
}
|
||||
});
|
||||
if transferred {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_items(&mut self) {
|
||||
let config = &self.config;
|
||||
|
||||
self.globals
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.globals.rebuild();
|
||||
|
||||
self.constants
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.constants.rebuild();
|
||||
|
||||
self.structs
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.structs.rebuild();
|
||||
|
||||
self.unions
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.unions.rebuild();
|
||||
|
||||
self.enums
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.enums.rebuild();
|
||||
|
||||
self.opaque_items
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.opaque_items.rebuild();
|
||||
|
||||
self.typedefs
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.typedefs.rebuild();
|
||||
|
||||
for item in &mut self.functions {
|
||||
item.rename_for_config(&self.config);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self) {
|
||||
if !self.config.style.generate_tag() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut resolver = DeclarationTypeResolver::default();
|
||||
|
||||
self.structs.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.enums.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.unions.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.typedefs.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
// NOTE: Intentionally last, so that in case there's an opaque type
|
||||
// which is conflicting with a non-opaque one, the later wins.
|
||||
self.opaque_items.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.enums
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.structs
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.unions
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.typedefs
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.globals
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
for item in &mut self.functions {
|
||||
item.resolve_declaration_types(&resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn simplify_standard_types(&mut self) {
|
||||
let config = &self.config;
|
||||
|
||||
self.structs.for_all_items_mut(|x| {
|
||||
x.simplify_standard_types(config);
|
||||
});
|
||||
self.unions.for_all_items_mut(|x| {
|
||||
x.simplify_standard_types(config);
|
||||
});
|
||||
self.globals.for_all_items_mut(|x| {
|
||||
x.simplify_standard_types(config);
|
||||
});
|
||||
self.typedefs.for_all_items_mut(|x| {
|
||||
x.simplify_standard_types(config);
|
||||
});
|
||||
for x in &mut self.functions {
|
||||
x.simplify_standard_types(config);
|
||||
}
|
||||
}
|
||||
|
||||
fn instantiate_monomorphs(&mut self) {
|
||||
// Collect a list of monomorphs
|
||||
let mut monomorphs = Monomorphs::default();
|
||||
|
||||
self.structs.for_all_items(|x| {
|
||||
x.add_monomorphs(self, &mut monomorphs);
|
||||
});
|
||||
self.unions.for_all_items(|x| {
|
||||
x.add_monomorphs(self, &mut monomorphs);
|
||||
});
|
||||
self.enums.for_all_items(|x| {
|
||||
x.add_monomorphs(self, &mut monomorphs);
|
||||
});
|
||||
self.typedefs.for_all_items(|x| {
|
||||
x.add_monomorphs(self, &mut monomorphs);
|
||||
});
|
||||
for x in &self.functions {
|
||||
x.add_monomorphs(self, &mut monomorphs);
|
||||
}
|
||||
|
||||
// Insert the monomorphs into self
|
||||
for monomorph in monomorphs.drain_structs() {
|
||||
self.structs.try_insert(monomorph);
|
||||
}
|
||||
for monomorph in monomorphs.drain_unions() {
|
||||
self.unions.try_insert(monomorph);
|
||||
}
|
||||
for monomorph in monomorphs.drain_opaques() {
|
||||
self.opaque_items.try_insert(monomorph);
|
||||
}
|
||||
for monomorph in monomorphs.drain_typedefs() {
|
||||
self.typedefs.try_insert(monomorph);
|
||||
}
|
||||
for monomorph in monomorphs.drain_enums() {
|
||||
self.enums.try_insert(monomorph);
|
||||
}
|
||||
|
||||
// Remove structs and opaque items that are generic
|
||||
self.opaque_items.filter(|x| x.generic_params.len() > 0);
|
||||
self.structs.filter(|x| x.generic_params.len() > 0);
|
||||
self.unions.filter(|x| x.generic_params.len() > 0);
|
||||
self.enums.filter(|x| x.generic_params.len() > 0);
|
||||
self.typedefs.filter(|x| x.generic_params.len() > 0);
|
||||
|
||||
// Mangle the paths that remain
|
||||
self.unions
|
||||
.for_all_items_mut(|x| x.mangle_paths(&monomorphs));
|
||||
self.structs
|
||||
.for_all_items_mut(|x| x.mangle_paths(&monomorphs));
|
||||
self.enums
|
||||
.for_all_items_mut(|x| x.mangle_paths(&monomorphs));
|
||||
self.typedefs
|
||||
.for_all_items_mut(|x| x.mangle_paths(&monomorphs));
|
||||
for x in &mut self.functions {
|
||||
x.mangle_paths(&monomorphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
291
zeroidc/vendor/cbindgen/src/bindgen/mangle.rs
vendored
Normal file
291
zeroidc/vendor/cbindgen/src/bindgen/mangle.rs
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 crate::bindgen::config::MangleConfig;
|
||||
use crate::bindgen::ir::{Path, Type};
|
||||
use crate::bindgen::rename::IdentifierType;
|
||||
|
||||
pub fn mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path {
|
||||
Path::new(mangle_name(path.name(), generic_values, config))
|
||||
}
|
||||
|
||||
pub fn mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String {
|
||||
Mangler::new(name, generic_values, /* last = */ true, config).mangle()
|
||||
}
|
||||
|
||||
enum Separator {
|
||||
OpeningAngleBracket = 1,
|
||||
Comma,
|
||||
ClosingAngleBracket,
|
||||
BeginMutPtr,
|
||||
BeginConstPtr,
|
||||
BeginFn,
|
||||
BetweenFnArg,
|
||||
EndFn,
|
||||
}
|
||||
|
||||
struct Mangler<'a> {
|
||||
input: &'a str,
|
||||
generic_values: &'a [Type],
|
||||
output: String,
|
||||
last: bool,
|
||||
config: &'a MangleConfig,
|
||||
}
|
||||
|
||||
impl<'a> Mangler<'a> {
|
||||
fn new(
|
||||
input: &'a str,
|
||||
generic_values: &'a [Type],
|
||||
last: bool,
|
||||
config: &'a MangleConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
input,
|
||||
generic_values,
|
||||
output: String::new(),
|
||||
last,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
fn mangle(mut self) -> String {
|
||||
self.mangle_internal();
|
||||
self.output
|
||||
}
|
||||
|
||||
fn push(&mut self, id: Separator) {
|
||||
let count = id as usize;
|
||||
let separator = if self.config.remove_underscores {
|
||||
""
|
||||
} else {
|
||||
"_"
|
||||
};
|
||||
self.output.extend(std::iter::repeat(separator).take(count));
|
||||
}
|
||||
|
||||
fn append_mangled_type(&mut self, ty: &Type, last: bool) {
|
||||
match *ty {
|
||||
Type::Path(ref generic) => {
|
||||
let sub_path =
|
||||
Mangler::new(generic.export_name(), generic.generics(), last, self.config)
|
||||
.mangle();
|
||||
|
||||
self.output.push_str(
|
||||
&self
|
||||
.config
|
||||
.rename_types
|
||||
.apply(&sub_path, IdentifierType::Type),
|
||||
);
|
||||
}
|
||||
Type::Primitive(ref primitive) => {
|
||||
self.output.push_str(
|
||||
&self
|
||||
.config
|
||||
.rename_types
|
||||
.apply(primitive.to_repr_rust(), IdentifierType::Type),
|
||||
);
|
||||
}
|
||||
Type::Ptr {
|
||||
ref ty, is_const, ..
|
||||
} => {
|
||||
self.push(if is_const {
|
||||
Separator::BeginConstPtr
|
||||
} else {
|
||||
Separator::BeginMutPtr
|
||||
});
|
||||
self.append_mangled_type(&**ty, last);
|
||||
}
|
||||
Type::FuncPtr {
|
||||
ref ret, ref args, ..
|
||||
} => {
|
||||
self.push(Separator::BeginFn);
|
||||
self.append_mangled_type(&**ret, args.is_empty());
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
self.push(Separator::BetweenFnArg);
|
||||
let last = last && i == args.len() - 1;
|
||||
self.append_mangled_type(&arg.1, last);
|
||||
}
|
||||
if !self.last {
|
||||
self.push(Separator::EndFn);
|
||||
}
|
||||
}
|
||||
Type::Array(..) => {
|
||||
unimplemented!(
|
||||
"Unable to mangle generic parameter {:?} for '{}'",
|
||||
ty,
|
||||
self.input
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mangle_internal(&mut self) {
|
||||
debug_assert!(self.output.is_empty());
|
||||
self.output = self.input.to_owned();
|
||||
if self.generic_values.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.push(Separator::OpeningAngleBracket);
|
||||
for (i, ty) in self.generic_values.iter().enumerate() {
|
||||
if i != 0 {
|
||||
self.push(Separator::Comma);
|
||||
}
|
||||
let last = self.last && i == self.generic_values.len() - 1;
|
||||
self.append_mangled_type(ty, last);
|
||||
}
|
||||
|
||||
// Skip writing the trailing '>' mangling when possible
|
||||
if !self.last {
|
||||
self.push(Separator::ClosingAngleBracket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generics() {
|
||||
use crate::bindgen::ir::{GenericPath, PrimitiveType};
|
||||
use crate::bindgen::rename::RenameRule::{self, PascalCase};
|
||||
|
||||
fn float() -> Type {
|
||||
Type::Primitive(PrimitiveType::Float)
|
||||
}
|
||||
|
||||
fn c_char() -> Type {
|
||||
Type::Primitive(PrimitiveType::Char)
|
||||
}
|
||||
|
||||
fn path(path: &str) -> Type {
|
||||
generic_path(path, &[])
|
||||
}
|
||||
|
||||
fn generic_path(path: &str, generics: &[Type]) -> Type {
|
||||
let path = Path::new(path);
|
||||
let generic_path = GenericPath::new(path, generics.to_owned());
|
||||
Type::Path(generic_path)
|
||||
}
|
||||
|
||||
// Foo<f32> => Foo_f32
|
||||
assert_eq!(
|
||||
mangle_path(&Path::new("Foo"), &[float()], &MangleConfig::default()),
|
||||
Path::new("Foo_f32")
|
||||
);
|
||||
|
||||
// Foo<Bar<f32>> => Foo_Bar_f32
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[float()])],
|
||||
&MangleConfig::default(),
|
||||
),
|
||||
Path::new("Foo_Bar_f32")
|
||||
);
|
||||
|
||||
// Foo<Bar> => Foo_Bar
|
||||
assert_eq!(
|
||||
mangle_path(&Path::new("Foo"), &[path("Bar")], &MangleConfig::default()),
|
||||
Path::new("Foo_Bar")
|
||||
);
|
||||
|
||||
// Foo<Bar> => FooBar
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[path("Bar")],
|
||||
&MangleConfig {
|
||||
remove_underscores: true,
|
||||
rename_types: RenameRule::None,
|
||||
}
|
||||
),
|
||||
Path::new("FooBar")
|
||||
);
|
||||
|
||||
// Foo<Bar<f32>> => FooBarF32
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[float()])],
|
||||
&MangleConfig {
|
||||
remove_underscores: true,
|
||||
rename_types: PascalCase,
|
||||
},
|
||||
),
|
||||
Path::new("FooBarF32")
|
||||
);
|
||||
|
||||
// Foo<Bar<c_char>> => FooBarCChar
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[c_char()])],
|
||||
&MangleConfig {
|
||||
remove_underscores: true,
|
||||
rename_types: PascalCase,
|
||||
},
|
||||
),
|
||||
Path::new("FooBarCChar")
|
||||
);
|
||||
|
||||
// Foo<Bar<T>> => Foo_Bar_T
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[path("T")])],
|
||||
&MangleConfig::default(),
|
||||
),
|
||||
Path::new("Foo_Bar_T")
|
||||
);
|
||||
|
||||
// Foo<Bar<T>, E> => Foo_Bar_T_____E
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[path("T")]), path("E")],
|
||||
&MangleConfig::default(),
|
||||
),
|
||||
Path::new("Foo_Bar_T_____E")
|
||||
);
|
||||
|
||||
// Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[
|
||||
generic_path("Bar", &[path("T")]),
|
||||
generic_path("Bar", &[path("E")]),
|
||||
],
|
||||
&MangleConfig::default(),
|
||||
),
|
||||
Path::new("Foo_Bar_T_____Bar_E")
|
||||
);
|
||||
|
||||
// Foo<Bar<T>, E> => FooBarTE
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[generic_path("Bar", &[path("T")]), path("E")],
|
||||
&MangleConfig {
|
||||
remove_underscores: true,
|
||||
rename_types: PascalCase,
|
||||
},
|
||||
),
|
||||
Path::new("FooBarTE")
|
||||
);
|
||||
|
||||
// Foo<Bar<T>, Bar<E>> => FooBarTBarE
|
||||
assert_eq!(
|
||||
mangle_path(
|
||||
&Path::new("Foo"),
|
||||
&[
|
||||
generic_path("Bar", &[path("T")]),
|
||||
generic_path("Bar", &[path("E")]),
|
||||
],
|
||||
&MangleConfig {
|
||||
remove_underscores: true,
|
||||
rename_types: PascalCase,
|
||||
},
|
||||
),
|
||||
Path::new("FooBarTBarE")
|
||||
);
|
||||
}
|
||||
65
zeroidc/vendor/cbindgen/src/bindgen/mod.rs
vendored
Normal file
65
zeroidc/vendor/cbindgen/src/bindgen/mod.rs
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
/// A helper macro for deriving deserialize for an enum to be used in toml-rs.
|
||||
/// This macro works be relying on an existing FromStr implementation for the
|
||||
/// desired type.
|
||||
macro_rules! deserialize_enum_str {
|
||||
($name:ident) => {
|
||||
impl<'de> ::serde::Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::Deserializer<'de>,
|
||||
{
|
||||
struct Visitor;
|
||||
impl<'de> ::serde::de::Visitor<'de> for Visitor {
|
||||
type Value = $name;
|
||||
|
||||
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
f.write_str("$name")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<$name, E>
|
||||
where
|
||||
E: ::serde::de::Error,
|
||||
{
|
||||
match v.parse::<$name>() {
|
||||
Ok(v) => Ok(v),
|
||||
Err(m) => Err(E::custom(m)),
|
||||
}
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_str(Visitor)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mod bindings;
|
||||
mod bitflags;
|
||||
mod builder;
|
||||
mod cargo;
|
||||
mod cdecl;
|
||||
mod config;
|
||||
mod declarationtyperesolver;
|
||||
mod dependencies;
|
||||
mod error;
|
||||
mod ir;
|
||||
mod library;
|
||||
mod mangle;
|
||||
mod monomorph;
|
||||
mod parser;
|
||||
mod rename;
|
||||
mod reserved;
|
||||
mod utilities;
|
||||
mod writer;
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) use self::cargo::*;
|
||||
|
||||
pub use self::bindings::Bindings;
|
||||
pub use self::builder::Builder;
|
||||
pub use self::config::Profile; // disambiguate with cargo::Profile
|
||||
pub use self::config::*;
|
||||
pub use self::error::Error;
|
||||
145
zeroidc/vendor/cbindgen/src/bindgen/monomorph.rs
vendored
Normal file
145
zeroidc/vendor/cbindgen/src/bindgen/monomorph.rs
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::collections::HashMap;
|
||||
use std::mem;
|
||||
|
||||
use crate::bindgen::ir::{Enum, GenericPath, OpaqueItem, Path, Struct, Type, Typedef, Union};
|
||||
use crate::bindgen::library::Library;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Monomorphs {
|
||||
replacements: HashMap<GenericPath, Path>,
|
||||
opaques: Vec<OpaqueItem>,
|
||||
structs: Vec<Struct>,
|
||||
unions: Vec<Union>,
|
||||
typedefs: Vec<Typedef>,
|
||||
enums: Vec<Enum>,
|
||||
}
|
||||
|
||||
impl Monomorphs {
|
||||
pub fn contains(&self, path: &GenericPath) -> bool {
|
||||
self.replacements.contains_key(path)
|
||||
}
|
||||
|
||||
pub fn insert_struct(
|
||||
&mut self,
|
||||
library: &Library,
|
||||
generic: &Struct,
|
||||
monomorph: Struct,
|
||||
parameters: Vec<Type>,
|
||||
) {
|
||||
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
|
||||
|
||||
debug_assert!(generic.generic_params.len() > 0);
|
||||
debug_assert!(!self.contains(&replacement_path));
|
||||
|
||||
self.replacements
|
||||
.insert(replacement_path, monomorph.path.clone());
|
||||
|
||||
monomorph.add_monomorphs(library, self);
|
||||
|
||||
self.structs.push(monomorph);
|
||||
}
|
||||
|
||||
pub fn insert_enum(
|
||||
&mut self,
|
||||
library: &Library,
|
||||
generic: &Enum,
|
||||
monomorph: Enum,
|
||||
parameters: Vec<Type>,
|
||||
) {
|
||||
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
|
||||
|
||||
debug_assert!(generic.generic_params.len() > 0);
|
||||
debug_assert!(!self.contains(&replacement_path));
|
||||
|
||||
self.replacements
|
||||
.insert(replacement_path, monomorph.path.clone());
|
||||
|
||||
monomorph.add_monomorphs(library, self);
|
||||
|
||||
self.enums.push(monomorph);
|
||||
}
|
||||
|
||||
pub fn insert_union(
|
||||
&mut self,
|
||||
library: &Library,
|
||||
generic: &Union,
|
||||
monomorph: Union,
|
||||
parameters: Vec<Type>,
|
||||
) {
|
||||
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
|
||||
|
||||
debug_assert!(generic.generic_params.len() > 0);
|
||||
debug_assert!(!self.contains(&replacement_path));
|
||||
|
||||
self.replacements
|
||||
.insert(replacement_path, monomorph.path.clone());
|
||||
|
||||
monomorph.add_monomorphs(library, self);
|
||||
|
||||
self.unions.push(monomorph);
|
||||
}
|
||||
|
||||
pub fn insert_opaque(
|
||||
&mut self,
|
||||
generic: &OpaqueItem,
|
||||
monomorph: OpaqueItem,
|
||||
parameters: Vec<Type>,
|
||||
) {
|
||||
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
|
||||
|
||||
debug_assert!(generic.generic_params.len() > 0);
|
||||
debug_assert!(!self.contains(&replacement_path));
|
||||
|
||||
self.replacements
|
||||
.insert(replacement_path, monomorph.path.clone());
|
||||
self.opaques.push(monomorph);
|
||||
}
|
||||
|
||||
pub fn insert_typedef(
|
||||
&mut self,
|
||||
library: &Library,
|
||||
generic: &Typedef,
|
||||
monomorph: Typedef,
|
||||
parameters: Vec<Type>,
|
||||
) {
|
||||
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
|
||||
|
||||
debug_assert!(generic.generic_params.len() > 0);
|
||||
debug_assert!(!self.contains(&replacement_path));
|
||||
|
||||
self.replacements
|
||||
.insert(replacement_path, monomorph.path.clone());
|
||||
|
||||
monomorph.add_monomorphs(library, self);
|
||||
|
||||
self.typedefs.push(monomorph);
|
||||
}
|
||||
|
||||
pub fn mangle_path(&self, path: &GenericPath) -> Option<&Path> {
|
||||
self.replacements.get(path)
|
||||
}
|
||||
|
||||
pub fn drain_opaques(&mut self) -> Vec<OpaqueItem> {
|
||||
mem::take(&mut self.opaques)
|
||||
}
|
||||
|
||||
pub fn drain_structs(&mut self) -> Vec<Struct> {
|
||||
mem::take(&mut self.structs)
|
||||
}
|
||||
|
||||
pub fn drain_unions(&mut self) -> Vec<Union> {
|
||||
mem::take(&mut self.unions)
|
||||
}
|
||||
|
||||
pub fn drain_typedefs(&mut self) -> Vec<Typedef> {
|
||||
mem::take(&mut self.typedefs)
|
||||
}
|
||||
|
||||
pub fn drain_enums(&mut self) -> Vec<Enum> {
|
||||
mem::take(&mut self.enums)
|
||||
}
|
||||
}
|
||||
1036
zeroidc/vendor/cbindgen/src/bindgen/parser.rs
vendored
Normal file
1036
zeroidc/vendor/cbindgen/src/bindgen/parser.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
145
zeroidc/vendor/cbindgen/src/bindgen/rename.rs
vendored
Normal file
145
zeroidc/vendor/cbindgen/src/bindgen/rename.rs
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::str::FromStr;
|
||||
|
||||
/// The type of identifier to be renamed.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum IdentifierType<'a> {
|
||||
StructMember,
|
||||
EnumVariant { prefix: &'a str },
|
||||
FunctionArg,
|
||||
Type,
|
||||
Enum,
|
||||
}
|
||||
|
||||
impl<'a> IdentifierType<'a> {
|
||||
fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
IdentifierType::StructMember => "m",
|
||||
IdentifierType::EnumVariant { .. } => "",
|
||||
IdentifierType::FunctionArg => "a",
|
||||
IdentifierType::Type => "",
|
||||
IdentifierType::Enum => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A rule to apply to an identifier when generating bindings.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum RenameRule {
|
||||
/// Do not apply any renaming. The default.
|
||||
None,
|
||||
/// Converts the identifier to PascalCase and adds a context dependent prefix
|
||||
GeckoCase,
|
||||
/// Converts the identifier to lower case.
|
||||
LowerCase,
|
||||
/// Converts the identifier to upper case.
|
||||
UpperCase,
|
||||
/// Converts the identifier to PascalCase.
|
||||
PascalCase,
|
||||
/// Converts the identifier to camelCase.
|
||||
CamelCase,
|
||||
/// Converts the identifier to snake_case.
|
||||
SnakeCase,
|
||||
/// Converts the identifier to SCREAMING_SNAKE_CASE.
|
||||
ScreamingSnakeCase,
|
||||
/// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
|
||||
/// with the enum name.
|
||||
QualifiedScreamingSnakeCase,
|
||||
}
|
||||
|
||||
impl RenameRule {
|
||||
pub(crate) fn not_none(self) -> Option<Self> {
|
||||
match self {
|
||||
RenameRule::None => None,
|
||||
other => Some(other),
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the rename rule to a string
|
||||
pub fn apply<'a>(self, text: &'a str, context: IdentifierType) -> Cow<'a, str> {
|
||||
use heck::*;
|
||||
|
||||
if text.is_empty() {
|
||||
return Cow::Borrowed(text);
|
||||
}
|
||||
|
||||
Cow::Owned(match self {
|
||||
RenameRule::None => return Cow::Borrowed(text),
|
||||
RenameRule::GeckoCase => context.to_str().to_owned() + &text.to_camel_case(),
|
||||
RenameRule::LowerCase => text.to_lowercase(),
|
||||
RenameRule::UpperCase => text.to_uppercase(),
|
||||
RenameRule::PascalCase => text.to_camel_case(),
|
||||
RenameRule::CamelCase => text.to_mixed_case(),
|
||||
RenameRule::SnakeCase => text.to_snake_case(),
|
||||
RenameRule::ScreamingSnakeCase => text.to_shouty_snake_case(),
|
||||
RenameRule::QualifiedScreamingSnakeCase => {
|
||||
let mut result = String::new();
|
||||
|
||||
if let IdentifierType::EnumVariant { prefix } = context {
|
||||
result.push_str(
|
||||
&RenameRule::ScreamingSnakeCase.apply(prefix, IdentifierType::Enum),
|
||||
);
|
||||
result.push('_');
|
||||
}
|
||||
|
||||
result.push_str(&RenameRule::ScreamingSnakeCase.apply(text, context));
|
||||
result
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RenameRule {
|
||||
fn default() -> RenameRule {
|
||||
RenameRule::None
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for RenameRule {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
|
||||
match s {
|
||||
"none" => Ok(RenameRule::None),
|
||||
"None" => Ok(RenameRule::None),
|
||||
|
||||
"mGeckoCase" => Ok(RenameRule::GeckoCase),
|
||||
"GeckoCase" => Ok(RenameRule::GeckoCase),
|
||||
"gecko_case" => Ok(RenameRule::GeckoCase),
|
||||
|
||||
"lowercase" => Ok(RenameRule::LowerCase),
|
||||
"LowerCase" => Ok(RenameRule::LowerCase),
|
||||
"lower_case" => Ok(RenameRule::LowerCase),
|
||||
|
||||
"UPPERCASE" => Ok(RenameRule::UpperCase),
|
||||
"UpperCase" => Ok(RenameRule::UpperCase),
|
||||
"upper_case" => Ok(RenameRule::UpperCase),
|
||||
|
||||
"PascalCase" => Ok(RenameRule::PascalCase),
|
||||
"pascal_case" => Ok(RenameRule::PascalCase),
|
||||
|
||||
"camelCase" => Ok(RenameRule::CamelCase),
|
||||
"CamelCase" => Ok(RenameRule::CamelCase),
|
||||
"camel_case" => Ok(RenameRule::CamelCase),
|
||||
|
||||
"snake_case" => Ok(RenameRule::SnakeCase),
|
||||
"SnakeCase" => Ok(RenameRule::SnakeCase),
|
||||
|
||||
"SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
|
||||
"ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
|
||||
"screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),
|
||||
|
||||
"QUALIFIED_SCREAMING_SNAKE_CASE" => Ok(RenameRule::QualifiedScreamingSnakeCase),
|
||||
"QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase),
|
||||
"qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase),
|
||||
|
||||
_ => Err(format!("Unrecognized RenameRule: '{}'.", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserialize_enum_str!(RenameRule);
|
||||
91
zeroidc/vendor/cbindgen/src/bindgen/reserved.rs
vendored
Normal file
91
zeroidc/vendor/cbindgen/src/bindgen/reserved.rs
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
/// Taken from `https://en.cppreference.com/w/cpp/keyword`
|
||||
/// Some experimental keywords were filtered out and the resulting list was
|
||||
/// sorted using a rust program.
|
||||
const RESERVED_KEYWORDS: &[&str] = &[
|
||||
"alignas",
|
||||
"alignof",
|
||||
"auto",
|
||||
"bool",
|
||||
"break",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"char16_t",
|
||||
"char32_t",
|
||||
"char8_t",
|
||||
"class",
|
||||
"const",
|
||||
"const_cast",
|
||||
"consteval",
|
||||
"constexpr",
|
||||
"continue",
|
||||
"decltype",
|
||||
"default",
|
||||
"delete",
|
||||
"do",
|
||||
"double",
|
||||
"dynamic_cast",
|
||||
"else",
|
||||
"enum",
|
||||
"explicit",
|
||||
"export",
|
||||
"extern",
|
||||
"false",
|
||||
"float",
|
||||
"for",
|
||||
"friend",
|
||||
"goto",
|
||||
"if",
|
||||
"inline",
|
||||
"int",
|
||||
"long",
|
||||
"mutable",
|
||||
"namespace",
|
||||
"new",
|
||||
"noexcept",
|
||||
"nullptr",
|
||||
"operator",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"register",
|
||||
"reinterpret_cast",
|
||||
"return",
|
||||
"short",
|
||||
"signed",
|
||||
"sizeof",
|
||||
"static",
|
||||
"static_assert",
|
||||
"static_cast",
|
||||
"struct",
|
||||
"switch",
|
||||
"template",
|
||||
"this",
|
||||
"thread_local",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
"typedef",
|
||||
"typename",
|
||||
"union",
|
||||
"unsigned",
|
||||
"using",
|
||||
"virtual",
|
||||
"void",
|
||||
"volatile",
|
||||
"wchar_t",
|
||||
"while",
|
||||
];
|
||||
|
||||
pub fn escape(rust_identifier: &mut String) {
|
||||
if RESERVED_KEYWORDS
|
||||
.binary_search(&rust_identifier.as_ref())
|
||||
.is_ok()
|
||||
{
|
||||
rust_identifier.push('_');
|
||||
}
|
||||
}
|
||||
293
zeroidc/vendor/cbindgen/src/bindgen/utilities.rs
vendored
Normal file
293
zeroidc/vendor/cbindgen/src/bindgen/utilities.rs
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#![allow(clippy::redundant_closure_call)]
|
||||
|
||||
pub trait IterHelpers: Iterator {
|
||||
fn try_skip_map<F, T, E>(&mut self, f: F) -> Result<Vec<T>, E>
|
||||
where
|
||||
F: FnMut(&Self::Item) -> Result<Option<T>, E>;
|
||||
}
|
||||
|
||||
impl<I> IterHelpers for I
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
fn try_skip_map<F, T, E>(&mut self, mut f: F) -> Result<Vec<T>, E>
|
||||
where
|
||||
F: FnMut(&Self::Item) -> Result<Option<T>, E>,
|
||||
{
|
||||
let mut out = Vec::new();
|
||||
for item in self {
|
||||
if let Some(x) = f(&item)? {
|
||||
out.push(x);
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SynItemFnHelpers: SynAttributeHelpers {
|
||||
fn exported_name(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
impl SynItemFnHelpers for syn::ItemFn {
|
||||
fn exported_name(&self) -> Option<String> {
|
||||
self.attrs
|
||||
.attr_name_value_lookup("export_name")
|
||||
.or_else(|| {
|
||||
if self.is_no_mangle() {
|
||||
Some(self.sig.ident.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SynItemFnHelpers for syn::ImplItemMethod {
|
||||
fn exported_name(&self) -> Option<String> {
|
||||
self.attrs
|
||||
.attr_name_value_lookup("export_name")
|
||||
.or_else(|| {
|
||||
if self.is_no_mangle() {
|
||||
Some(self.sig.ident.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this attribute causes us to skip at item. This basically
|
||||
/// checks for `#[cfg(test)]`, `#[test]`, `/// cbindgen::ignore` and
|
||||
/// variations thereof.
|
||||
fn is_skip_item_attr(attr: &syn::Meta) -> bool {
|
||||
match *attr {
|
||||
syn::Meta::Path(ref path) => {
|
||||
// TODO(emilio): It'd be great if rustc allowed us to use a syntax
|
||||
// like `#[cbindgen::ignore]` or such.
|
||||
path.is_ident("test")
|
||||
}
|
||||
syn::Meta::List(ref list) => {
|
||||
if !list.path.is_ident("cfg") {
|
||||
return false;
|
||||
}
|
||||
list.nested.iter().any(|nested| match *nested {
|
||||
syn::NestedMeta::Meta(ref meta) => is_skip_item_attr(meta),
|
||||
syn::NestedMeta::Lit(..) => false,
|
||||
})
|
||||
}
|
||||
syn::Meta::NameValue(ref name_value) => {
|
||||
if name_value.path.is_ident("doc") {
|
||||
if let syn::Lit::Str(ref content) = name_value.lit {
|
||||
// FIXME(emilio): Maybe should use the general annotation
|
||||
// mechanism, but it seems overkill for this.
|
||||
if content.value().trim() == "cbindgen:ignore" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SynAttributeHelpers {
|
||||
/// Returns the list of attributes for an item.
|
||||
fn attrs(&self) -> &[syn::Attribute];
|
||||
|
||||
/// Searches for attributes like `#[test]`.
|
||||
/// Example:
|
||||
/// - `item.has_attr_word("test")` => `#[test]`
|
||||
fn has_attr_word(&self, name: &str) -> bool {
|
||||
self.attrs()
|
||||
.iter()
|
||||
.filter_map(|x| x.parse_meta().ok())
|
||||
.any(|attr| {
|
||||
if let syn::Meta::Path(ref path) = attr {
|
||||
path.is_ident(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_no_mangle(&self) -> bool {
|
||||
self.has_attr_word("no_mangle")
|
||||
}
|
||||
|
||||
/// Sees whether we should skip parsing a given item.
|
||||
fn should_skip_parsing(&self) -> bool {
|
||||
for attr in self.attrs() {
|
||||
let meta = match attr.parse_meta() {
|
||||
Ok(attr) => attr,
|
||||
Err(..) => return false,
|
||||
};
|
||||
if is_skip_item_attr(&meta) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn attr_name_value_lookup(&self, name: &str) -> Option<String> {
|
||||
self.attrs()
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
let attr = attr.parse_meta().ok()?;
|
||||
if let syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) = attr
|
||||
{
|
||||
if path.is_ident(name) {
|
||||
return Some(lit.value());
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.next()
|
||||
}
|
||||
|
||||
fn get_comment_lines(&self) -> Vec<String> {
|
||||
let mut comment = Vec::new();
|
||||
|
||||
for attr in self.attrs() {
|
||||
if attr.style == syn::AttrStyle::Outer {
|
||||
if let Ok(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(content),
|
||||
..
|
||||
})) = attr.parse_meta()
|
||||
{
|
||||
if path.is_ident("doc") {
|
||||
comment.extend(split_doc_attr(&content.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comment
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! syn_item_match_helper {
|
||||
($s:ident => has_attrs: |$i:ident| $a:block, otherwise: || $b:block) => {
|
||||
match *$s {
|
||||
syn::Item::Const(ref $i) => $a,
|
||||
syn::Item::Enum(ref $i) => $a,
|
||||
syn::Item::ExternCrate(ref $i) => $a,
|
||||
syn::Item::Fn(ref $i) => $a,
|
||||
syn::Item::ForeignMod(ref $i) => $a,
|
||||
syn::Item::Impl(ref $i) => $a,
|
||||
syn::Item::Macro(ref $i) => $a,
|
||||
syn::Item::Macro2(ref $i) => $a,
|
||||
syn::Item::Mod(ref $i) => $a,
|
||||
syn::Item::Static(ref $i) => $a,
|
||||
syn::Item::Struct(ref $i) => $a,
|
||||
syn::Item::Trait(ref $i) => $a,
|
||||
syn::Item::Type(ref $i) => $a,
|
||||
syn::Item::Union(ref $i) => $a,
|
||||
syn::Item::Use(ref $i) => $a,
|
||||
syn::Item::TraitAlias(ref $i) => $a,
|
||||
syn::Item::Verbatim(_) => $b,
|
||||
_ => panic!("Unhandled syn::Item: {:?}", $s),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl SynAttributeHelpers for syn::Item {
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
syn_item_match_helper!(self =>
|
||||
has_attrs: |item| { &item.attrs },
|
||||
otherwise: || { &[] }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_syn_item_helper {
|
||||
($t:ty) => {
|
||||
impl SynAttributeHelpers for $t {
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_syn_item_helper!(syn::ItemExternCrate);
|
||||
impl_syn_item_helper!(syn::ItemUse);
|
||||
impl_syn_item_helper!(syn::ItemStatic);
|
||||
impl_syn_item_helper!(syn::ItemConst);
|
||||
impl_syn_item_helper!(syn::ItemFn);
|
||||
impl_syn_item_helper!(syn::ImplItemMethod);
|
||||
impl_syn_item_helper!(syn::ItemMod);
|
||||
impl_syn_item_helper!(syn::ItemForeignMod);
|
||||
impl_syn_item_helper!(syn::ItemType);
|
||||
impl_syn_item_helper!(syn::ItemStruct);
|
||||
impl_syn_item_helper!(syn::ItemEnum);
|
||||
impl_syn_item_helper!(syn::ItemUnion);
|
||||
impl_syn_item_helper!(syn::ItemTrait);
|
||||
impl_syn_item_helper!(syn::ItemImpl);
|
||||
impl_syn_item_helper!(syn::ItemMacro);
|
||||
impl_syn_item_helper!(syn::ItemMacro2);
|
||||
impl_syn_item_helper!(syn::ItemTraitAlias);
|
||||
|
||||
/// Helper function for accessing Abi information
|
||||
pub trait SynAbiHelpers {
|
||||
fn is_c(&self) -> bool;
|
||||
fn is_omitted(&self) -> bool;
|
||||
}
|
||||
|
||||
impl SynAbiHelpers for Option<syn::Abi> {
|
||||
fn is_c(&self) -> bool {
|
||||
if let Some(ref abi) = *self {
|
||||
if let Some(ref lit_string) = abi.name {
|
||||
return lit_string.value() == "C";
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
fn is_omitted(&self) -> bool {
|
||||
if let Some(ref abi) = *self {
|
||||
abi.name.is_none()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SynAbiHelpers for syn::Abi {
|
||||
fn is_c(&self) -> bool {
|
||||
if let Some(ref lit_string) = self.name {
|
||||
lit_string.value() == "C"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn is_omitted(&self) -> bool {
|
||||
self.name.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl SynAttributeHelpers for [syn::Attribute] {
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn split_doc_attr(input: &str) -> Vec<String> {
|
||||
input
|
||||
// Convert two newline (indicate "new paragraph") into two line break.
|
||||
.replace("\n\n", " \n \n")
|
||||
// Convert newline after two spaces (indicate "line break") into line break.
|
||||
.split(" \n")
|
||||
// Convert single newline (indicate hard-wrapped) into space.
|
||||
.map(|s| s.replace('\n', " "))
|
||||
.map(|s| s.trim_end().to_string())
|
||||
.collect()
|
||||
}
|
||||
258
zeroidc/vendor/cbindgen/src/bindgen/writer.rs
vendored
Normal file
258
zeroidc/vendor/cbindgen/src/bindgen/writer.rs
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::cmp;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::config::{Braces, Config, Language};
|
||||
use crate::bindgen::Bindings;
|
||||
|
||||
/// A type of way to format a list.
|
||||
pub enum ListType<'a> {
|
||||
/// Join each adjacent item with a str.
|
||||
Join(&'a str),
|
||||
/// End each item with a str.
|
||||
Cap(&'a str),
|
||||
}
|
||||
|
||||
/// An empty file used for creating a null source writer and measuring line
|
||||
/// metrics for various code layouts.
|
||||
pub struct NullFile;
|
||||
impl Write for NullFile {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
Ok(buf.len())
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A utility wrapper to write unbuffered data and correctly adjust positions.
|
||||
struct InnerWriter<'a, 'b: 'a, F: 'a + Write>(&'a mut SourceWriter<'b, F>);
|
||||
|
||||
impl<'a, 'b, F: Write> Write for InnerWriter<'a, 'b, F> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let writer = &mut self.0;
|
||||
|
||||
if !writer.line_started {
|
||||
for _ in 0..writer.spaces() {
|
||||
write!(writer.out, " ").unwrap();
|
||||
}
|
||||
writer.line_started = true;
|
||||
writer.line_length += writer.spaces();
|
||||
}
|
||||
|
||||
let written = writer.out.write(buf)?;
|
||||
writer.line_length += written;
|
||||
writer.max_line_length = cmp::max(writer.max_line_length, writer.line_length);
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.out.flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A utility writer for generating code easier.
|
||||
pub struct SourceWriter<'a, F: Write> {
|
||||
out: F,
|
||||
bindings: &'a Bindings,
|
||||
spaces: Vec<usize>,
|
||||
line_started: bool,
|
||||
line_length: usize,
|
||||
line_number: usize,
|
||||
max_line_length: usize,
|
||||
}
|
||||
|
||||
pub type MeasureWriter<'a> = SourceWriter<'a, NullFile>;
|
||||
|
||||
impl<'a, F: Write> SourceWriter<'a, F> {
|
||||
pub fn new(out: F, bindings: &'a Bindings) -> Self {
|
||||
SourceWriter {
|
||||
out,
|
||||
bindings,
|
||||
spaces: vec![0],
|
||||
line_started: false,
|
||||
line_length: 0,
|
||||
line_number: 1,
|
||||
max_line_length: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bindings(&self) -> &Bindings {
|
||||
self.bindings
|
||||
}
|
||||
|
||||
/// Takes a function that writes source and returns the maximum line length
|
||||
/// written.
|
||||
pub fn measure<T>(&self, func: T) -> usize
|
||||
where
|
||||
T: Fn(&mut MeasureWriter),
|
||||
{
|
||||
let mut measurer = SourceWriter {
|
||||
out: NullFile,
|
||||
bindings: self.bindings,
|
||||
spaces: self.spaces.clone(),
|
||||
line_started: self.line_started,
|
||||
line_length: self.line_length,
|
||||
line_number: self.line_number,
|
||||
max_line_length: self.line_length,
|
||||
};
|
||||
|
||||
func(&mut measurer);
|
||||
|
||||
measurer.max_line_length
|
||||
}
|
||||
|
||||
fn spaces(&self) -> usize {
|
||||
*self.spaces.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn push_set_spaces(&mut self, spaces: usize) {
|
||||
self.spaces.push(spaces);
|
||||
}
|
||||
|
||||
pub fn pop_set_spaces(&mut self) {
|
||||
self.pop_tab()
|
||||
}
|
||||
|
||||
pub fn line_length_for_align(&self) -> usize {
|
||||
if self.line_started {
|
||||
self.line_length
|
||||
} else {
|
||||
self.line_length + self.spaces()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_tab(&mut self) {
|
||||
let spaces = self.spaces() - (self.spaces() % self.bindings.config.tab_width)
|
||||
+ self.bindings.config.tab_width;
|
||||
self.spaces.push(spaces);
|
||||
}
|
||||
|
||||
pub fn pop_tab(&mut self) {
|
||||
assert!(!self.spaces.is_empty());
|
||||
self.spaces.pop();
|
||||
}
|
||||
|
||||
pub fn new_line(&mut self) {
|
||||
self.out
|
||||
.write_all(self.bindings.config.line_endings.as_str().as_bytes())
|
||||
.unwrap();
|
||||
self.line_started = false;
|
||||
self.line_length = 0;
|
||||
self.line_number += 1;
|
||||
}
|
||||
|
||||
pub fn new_line_if_not_start(&mut self) {
|
||||
if self.line_number != 1 {
|
||||
self.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_brace(&mut self) {
|
||||
match self.bindings.config.language {
|
||||
Language::Cxx | Language::C => match self.bindings.config.braces {
|
||||
Braces::SameLine => {
|
||||
self.write(" {");
|
||||
self.push_tab();
|
||||
self.new_line();
|
||||
}
|
||||
Braces::NextLine => {
|
||||
self.new_line();
|
||||
self.write("{");
|
||||
self.push_tab();
|
||||
self.new_line();
|
||||
}
|
||||
},
|
||||
Language::Cython => {
|
||||
self.write(":");
|
||||
self.new_line();
|
||||
self.push_tab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close_brace(&mut self, semicolon: bool) {
|
||||
self.pop_tab();
|
||||
match self.bindings.config.language {
|
||||
Language::Cxx | Language::C => {
|
||||
self.new_line();
|
||||
if semicolon {
|
||||
self.write("};");
|
||||
} else {
|
||||
self.write("}");
|
||||
}
|
||||
}
|
||||
Language::Cython => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, text: &'static str) {
|
||||
write!(self, "{}", text);
|
||||
}
|
||||
|
||||
pub fn write_raw_block(&mut self, block: &str) {
|
||||
self.line_started = true;
|
||||
write!(self, "{}", block);
|
||||
}
|
||||
|
||||
pub fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) {
|
||||
InnerWriter(self).write_fmt(fmt).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_horizontal_source_list<'b, S: Source>(
|
||||
&mut self,
|
||||
items: &[S],
|
||||
list_type: ListType<'b>,
|
||||
) {
|
||||
for (i, item) in items.iter().enumerate() {
|
||||
item.write(&self.bindings.config, self);
|
||||
|
||||
match list_type {
|
||||
ListType::Join(text) => {
|
||||
if i != items.len() - 1 {
|
||||
write!(self, "{}", text);
|
||||
}
|
||||
}
|
||||
ListType::Cap(text) => {
|
||||
write!(self, "{}", text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_vertical_source_list<'b, S: Source>(
|
||||
&mut self,
|
||||
items: &[S],
|
||||
list_type: ListType<'b>,
|
||||
) {
|
||||
let align_length = self.line_length_for_align();
|
||||
self.push_set_spaces(align_length);
|
||||
for (i, item) in items.iter().enumerate() {
|
||||
item.write(&self.bindings.config, self);
|
||||
|
||||
match list_type {
|
||||
ListType::Join(text) => {
|
||||
if i != items.len() - 1 {
|
||||
write!(self, "{}", text);
|
||||
}
|
||||
}
|
||||
ListType::Cap(text) => {
|
||||
write!(self, "{}", text);
|
||||
}
|
||||
}
|
||||
|
||||
if i != items.len() - 1 {
|
||||
self.new_line();
|
||||
}
|
||||
}
|
||||
self.pop_tab();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Source {
|
||||
fn write<F: Write>(&self, config: &Config, _: &mut SourceWriter<F>);
|
||||
}
|
||||
41
zeroidc/vendor/cbindgen/src/lib.rs
vendored
Normal file
41
zeroidc/vendor/cbindgen/src/lib.rs
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate proc_macro2;
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
extern crate toml;
|
||||
|
||||
mod bindgen;
|
||||
|
||||
pub use crate::bindgen::*;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
/// A utility function for build scripts to generate bindings for a crate, using
|
||||
/// a `cbindgen.toml` if it exists.
|
||||
pub fn generate<P: AsRef<Path>>(crate_dir: P) -> Result<Bindings, Error> {
|
||||
let config = Config::from_root_or_default(crate_dir.as_ref());
|
||||
|
||||
generate_with_config(crate_dir, config)
|
||||
}
|
||||
|
||||
/// A utility function for build scripts to generate bindings for a crate with a
|
||||
/// custom config.
|
||||
pub fn generate_with_config<P: AsRef<Path>>(
|
||||
crate_dir: P,
|
||||
config: Config,
|
||||
) -> Result<Bindings, Error> {
|
||||
Builder::new()
|
||||
.with_config(config)
|
||||
.with_crate(crate_dir)
|
||||
.generate()
|
||||
}
|
||||
105
zeroidc/vendor/cbindgen/src/logging.rs
vendored
Normal file
105
zeroidc/vendor/cbindgen/src/logging.rs
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::io;
|
||||
use std::io::Write;
|
||||
|
||||
use log::*;
|
||||
|
||||
pub struct TraceLogger;
|
||||
pub struct WarnLogger;
|
||||
pub struct InfoLogger;
|
||||
pub struct ErrorLogger;
|
||||
|
||||
impl TraceLogger {
|
||||
pub fn init() -> Result<(), SetLoggerError> {
|
||||
log::set_logger(&InfoLogger)?;
|
||||
log::set_max_level(LevelFilter::Trace);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl log::Log for TraceLogger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Trace
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
eprintln!("{}: {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
io::stderr().flush().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl WarnLogger {
|
||||
pub fn init() -> Result<(), SetLoggerError> {
|
||||
log::set_logger(&InfoLogger)?;
|
||||
log::set_max_level(LevelFilter::Warn);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl log::Log for WarnLogger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Warn
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
eprintln!("{}: {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
io::stderr().flush().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorLogger {
|
||||
pub fn init() -> Result<(), SetLoggerError> {
|
||||
log::set_logger(&InfoLogger)?;
|
||||
log::set_max_level(LevelFilter::Error);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl log::Log for ErrorLogger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Error
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
eprintln!("{}: {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
io::stderr().flush().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoLogger {
|
||||
pub fn init() -> Result<(), SetLoggerError> {
|
||||
log::set_logger(&InfoLogger)?;
|
||||
log::set_max_level(LevelFilter::Info);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl log::Log for InfoLogger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Info
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
eprintln!("{}: {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
io::stderr().flush().unwrap();
|
||||
}
|
||||
}
|
||||
314
zeroidc/vendor/cbindgen/src/main.rs
vendored
Normal file
314
zeroidc/vendor/cbindgen/src/main.rs
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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::env;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate proc_macro2;
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
extern crate toml;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
|
||||
mod bindgen;
|
||||
mod logging;
|
||||
|
||||
use crate::bindgen::{Bindings, Builder, Cargo, Config, Error, Profile, Style};
|
||||
|
||||
fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
// We allow specifying a language to override the config default. This is
|
||||
// used by compile-tests.
|
||||
if let Some(lang) = matches.value_of("lang") {
|
||||
config.language = match lang.parse() {
|
||||
Ok(lang) => lang,
|
||||
Err(reason) => {
|
||||
error!("{}", reason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("cpp-compat") {
|
||||
config.cpp_compat = true;
|
||||
}
|
||||
|
||||
if matches.is_present("only-target-dependencies") {
|
||||
config.only_target_dependencies = true;
|
||||
}
|
||||
|
||||
if let Some(style) = matches.value_of("style") {
|
||||
config.style = match style {
|
||||
"Both" => Style::Both,
|
||||
"both" => Style::Both,
|
||||
"Tag" => Style::Tag,
|
||||
"tag" => Style::Tag,
|
||||
"Type" => Style::Type,
|
||||
"type" => Style::Type,
|
||||
_ => {
|
||||
error!("Unknown style specified.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(profile) = matches.value_of("profile") {
|
||||
config.parse.expand.profile = match Profile::from_str(profile) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("d") {
|
||||
config.parse.parse_deps = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn load_bindings<'a>(input: &Path, matches: &ArgMatches<'a>) -> Result<Bindings, Error> {
|
||||
// If a file is specified then we load it as a single source
|
||||
if !input.is_dir() {
|
||||
// Load any config specified or search in the input directory
|
||||
let mut config = match matches.value_of("config") {
|
||||
Some(c) => Config::from_file(c).unwrap(),
|
||||
None => Config::from_root_or_default(input),
|
||||
};
|
||||
|
||||
apply_config_overrides(&mut config, matches);
|
||||
|
||||
return Builder::new()
|
||||
.with_config(config)
|
||||
.with_src(input)
|
||||
.generate();
|
||||
}
|
||||
|
||||
// We have to load a whole crate, so we use cargo to gather metadata
|
||||
let lib = Cargo::load(
|
||||
input,
|
||||
matches.value_of("lockfile"),
|
||||
matches.value_of("crate"),
|
||||
true,
|
||||
matches.is_present("clean"),
|
||||
matches.is_present("only-target-dependencies"),
|
||||
matches.value_of("metadata").map(Path::new),
|
||||
)?;
|
||||
|
||||
// Load any config specified or search in the binding crate directory
|
||||
let mut config = match matches.value_of("config") {
|
||||
Some(c) => Config::from_file(c).unwrap(),
|
||||
None => {
|
||||
let binding_crate_dir = lib.find_crate_dir(&lib.binding_crate_ref());
|
||||
|
||||
if let Some(binding_crate_dir) = binding_crate_dir {
|
||||
Config::from_root_or_default(&binding_crate_dir)
|
||||
} else {
|
||||
// This shouldn't happen
|
||||
Config::from_root_or_default(input)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
apply_config_overrides(&mut config, matches);
|
||||
|
||||
Builder::new()
|
||||
.with_config(config)
|
||||
.with_cargo(lib)
|
||||
.generate()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("cbindgen")
|
||||
.version(bindgen::VERSION)
|
||||
.about("Generate C bindings for a Rust library")
|
||||
.arg(
|
||||
Arg::with_name("v")
|
||||
.short("v")
|
||||
.multiple(true)
|
||||
.help("Enable verbose logging"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("verify")
|
||||
.long("verify")
|
||||
.help("Generate bindings and compare it to the existing bindings file and error if they are different"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("config")
|
||||
.short("c")
|
||||
.long("config")
|
||||
.value_name("PATH")
|
||||
.help("Specify path to a `cbindgen.toml` config to use"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("lang")
|
||||
.short("l")
|
||||
.long("lang")
|
||||
.value_name("LANGUAGE")
|
||||
.help("Specify the language to output bindings in")
|
||||
.possible_values(&["c++", "C++", "c", "C", "cython", "Cython"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("cpp-compat")
|
||||
.long("cpp-compat")
|
||||
.help("Whether to add C++ compatibility to generated C bindings")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("only-target-dependencies")
|
||||
.long("only-target-dependencies")
|
||||
.help("Only fetch dependencies needed by the target platform. \
|
||||
The target platform defaults to the host platform; set TARGET to override.")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("style")
|
||||
.short("s")
|
||||
.long("style")
|
||||
.value_name("STYLE")
|
||||
.help("Specify the declaration style to use for bindings")
|
||||
.possible_values(&["Both", "both", "Tag", "tag", "Type", "type"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("d")
|
||||
.short("d")
|
||||
.long("parse-dependencies")
|
||||
.help("Whether to parse dependencies when generating bindings"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("clean")
|
||||
.long("clean")
|
||||
.help(
|
||||
"Whether to use a new temporary directory for expanding macros. \
|
||||
Affects performance, but might be required in certain build processes.")
|
||||
.required(false)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.help(
|
||||
"A crate directory or source file to generate bindings for. \
|
||||
In general this is the folder where the Cargo.toml file of \
|
||||
source Rust library resides.")
|
||||
.required(false)
|
||||
.index(1),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("crate")
|
||||
.long("crate")
|
||||
.value_name("CRATE_NAME")
|
||||
.help(
|
||||
"If generating bindings for a crate, \
|
||||
the specific crate to generate bindings for",
|
||||
)
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("out")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.value_name("PATH")
|
||||
.help("The file to output the bindings to")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("lockfile")
|
||||
.long("lockfile")
|
||||
.value_name("PATH")
|
||||
.help(
|
||||
"Specify the path to the Cargo.lock file explicitly. If this \
|
||||
is not specified, the Cargo.lock file is searched for in the \
|
||||
same folder as the Cargo.toml file. This option is useful for \
|
||||
projects that use workspaces.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("metadata")
|
||||
.long("metadata")
|
||||
.value_name("PATH")
|
||||
.help(
|
||||
"Specify the path to the output of a `cargo metadata` \
|
||||
command that allows to get dependency information. \
|
||||
This is useful because cargo metadata may be the longest \
|
||||
part of cbindgen runtime, and you may want to share it \
|
||||
across cbindgen invocations. By default cbindgen will run \
|
||||
`cargo metadata --all-features --format-version 1 \
|
||||
--manifest-path <path/to/crate/Cargo.toml>"
|
||||
)
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("profile")
|
||||
.long("profile")
|
||||
.value_name("PROFILE")
|
||||
.help(
|
||||
"Specify the profile to use when expanding macros. \
|
||||
Has no effect otherwise."
|
||||
)
|
||||
.possible_values(&["Debug", "debug", "Release", "release"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("quiet")
|
||||
.short("q")
|
||||
.long("quiet")
|
||||
.help("Report errors only (overrides verbosity options).")
|
||||
.required(false),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
if !matches.is_present("out") && matches.is_present("verify") {
|
||||
error!(
|
||||
"Cannot verify bindings against `stdout`, please specify a file to compare against."
|
||||
);
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
||||
// Initialize logging
|
||||
if matches.is_present("quiet") {
|
||||
logging::ErrorLogger::init().unwrap();
|
||||
} else {
|
||||
match matches.occurrences_of("v") {
|
||||
0 => logging::WarnLogger::init().unwrap(),
|
||||
1 => logging::InfoLogger::init().unwrap(),
|
||||
_ => logging::TraceLogger::init().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
// Find the input directory
|
||||
let input = match matches.value_of("INPUT") {
|
||||
Some(input) => PathBuf::from(input),
|
||||
None => env::current_dir().unwrap(),
|
||||
};
|
||||
|
||||
let bindings = match load_bindings(&input, &matches) {
|
||||
Ok(bindings) => bindings,
|
||||
Err(msg) => {
|
||||
error!("{}", msg);
|
||||
error!("Couldn't generate bindings for {}.", input.display());
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Write the bindings file
|
||||
match matches.value_of("out") {
|
||||
Some(file) => {
|
||||
let changed = bindings.write_to_file(file);
|
||||
|
||||
if matches.is_present("verify") && changed {
|
||||
error!("Bindings changed: {}", file);
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bindings.write(io::stdout());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user