blob: 5fe8d90d4c71efb4ef4f317f0048569d8f45df49 [file] [log] [blame]
mod item_discovery_callback;
use bindgen::callbacks::*;
use bindgen::FieldVisibilityKind;
#[derive(Debug)]
pub struct RemovePrefixParseCallback {
pub remove_prefix: Option<String>,
}
impl RemovePrefixParseCallback {
pub fn new(prefix: &str) -> Self {
RemovePrefixParseCallback {
remove_prefix: Some(prefix.to_string()),
}
}
}
impl ParseCallbacks for RemovePrefixParseCallback {
fn generated_name_override(&self, item_info: ItemInfo) -> Option<String> {
if let Some(prefix) = &self.remove_prefix {
let (expected_prefix, expected_suffix) = match item_info.kind {
ItemKind::Function => ("function_", "_name"),
ItemKind::Var => ("var_", "_name"),
_ => todo!(),
};
if let Some(name) = item_info.name.strip_prefix(prefix) {
assert!(name.starts_with(expected_prefix));
assert!(name.ends_with(expected_suffix));
return Some(name.to_string());
}
}
None
}
}
#[derive(Debug)]
pub struct PrefixLinkNameParseCallback {
pub prefix: Option<String>,
}
impl PrefixLinkNameParseCallback {
pub fn new(prefix: &str) -> Self {
PrefixLinkNameParseCallback {
prefix: Some(prefix.to_string()),
}
}
}
impl ParseCallbacks for PrefixLinkNameParseCallback {
fn generated_link_name_override(
&self,
item_info: ItemInfo,
) -> Option<String> {
self.prefix
.as_deref()
.map(|prefix| format!("{prefix}{}", item_info.name))
}
}
#[derive(Debug)]
struct EnumVariantRename;
impl ParseCallbacks for EnumVariantRename {
fn enum_variant_name(
&self,
_enum_name: Option<&str>,
original_variant_name: &str,
_variant_value: EnumVariantValue,
) -> Option<String> {
Some(format!("RENAMED_{original_variant_name}"))
}
}
#[derive(Debug)]
struct BlocklistedTypeImplementsTrait;
impl ParseCallbacks for BlocklistedTypeImplementsTrait {
fn blocklisted_type_implements_trait(
&self,
_name: &str,
derive_trait: DeriveTrait,
) -> Option<ImplementsTrait> {
if derive_trait == DeriveTrait::Hash {
Some(ImplementsTrait::No)
} else {
Some(ImplementsTrait::Yes)
}
}
}
#[derive(Debug)]
struct FieldVisibility {
default: FieldVisibilityKind,
}
/// Implements the `field_visibility` function of the trait by checking if the
/// field name starts with `private_`. If it does, it makes it private, if it
/// doesn't, it makes it public, taking into account the default visibility.
impl ParseCallbacks for FieldVisibility {
fn field_visibility(
&self,
FieldInfo { field_name, .. }: FieldInfo,
) -> Option<FieldVisibilityKind> {
match (self.default, field_name.starts_with("private_")) {
(FieldVisibilityKind::Private, false) => {
Some(FieldVisibilityKind::Public)
}
(FieldVisibilityKind::Public, true) => {
Some(FieldVisibilityKind::Private)
}
(FieldVisibilityKind::PublicCrate, _) => unimplemented!(),
_ => None,
}
}
}
#[derive(Debug)]
struct TypeVisibility;
/// Implements the `field_visibility` function of the trait by checking the
/// type name. Depending on name prefix, it will return a different visibility.
impl ParseCallbacks for TypeVisibility {
fn field_visibility(
&self,
FieldInfo { type_name, .. }: FieldInfo,
) -> Option<FieldVisibilityKind> {
if type_name.starts_with("private_") {
Some(FieldVisibilityKind::Private)
} else if type_name.starts_with("pubcrate_") {
Some(FieldVisibilityKind::PublicCrate)
} else if type_name.starts_with("pub_") {
Some(FieldVisibilityKind::Public)
} else {
None
}
}
}
#[derive(Debug)]
pub(super) struct WrapAsVariadicFn;
impl ParseCallbacks for WrapAsVariadicFn {
fn wrap_as_variadic_fn(&self, name: &str) -> Option<String> {
Some(name.to_owned() + "_wrapped")
}
}
#[derive(Debug)]
pub(super) struct OperatorRename;
impl ParseCallbacks for OperatorRename {
fn generated_name_override(&self, info: ItemInfo) -> Option<String> {
if info.name == "operator=" {
Some("operatorequals".to_string())
} else {
None
}
}
}
pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
match cb {
"enum-variant-rename" => Box::new(EnumVariantRename),
"blocklisted-type-implements-trait" => {
Box::new(BlocklistedTypeImplementsTrait)
}
"wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn),
"type-visibility" => Box::new(TypeVisibility),
"operator-rename" => Box::new(OperatorRename),
call_back => {
if let Some(prefix) =
call_back.strip_prefix("remove-function-prefix-")
{
let lnopc = RemovePrefixParseCallback::new(prefix);
Box::new(lnopc)
} else if let Some(prefix) =
call_back.strip_prefix("prefix-link-name-")
{
let plnpc = PrefixLinkNameParseCallback::new(prefix);
Box::new(plnpc)
} else if let Some(default) =
call_back.strip_prefix("field-visibility-default-")
{
Box::new(FieldVisibility {
default: default.parse().expect(
"unable to parse field-visibility-default callback",
),
})
} else {
panic!("Couldn't find name ParseCallbacks: {cb}")
}
}
}
}