• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use bindgen::callbacks::*;
2 use bindgen::FieldVisibilityKind;
3 
4 #[derive(Debug)]
5 pub struct RemovePrefixParseCallback {
6     pub remove_prefix: Option<String>,
7 }
8 
9 impl RemovePrefixParseCallback {
new(prefix: &str) -> Self10     pub fn new(prefix: &str) -> Self {
11         RemovePrefixParseCallback {
12             remove_prefix: Some(prefix.to_string()),
13         }
14     }
15 }
16 
17 impl ParseCallbacks for RemovePrefixParseCallback {
generated_name_override(&self, item_info: ItemInfo) -> Option<String>18     fn generated_name_override(&self, item_info: ItemInfo) -> Option<String> {
19         if let Some(prefix) = &self.remove_prefix {
20             let (expected_prefix, expected_suffix) = match item_info.kind {
21                 ItemKind::Function => ("function_", "_name"),
22                 ItemKind::Var => ("var_", "_name"),
23                 _ => todo!(),
24             };
25             if let Some(name) = item_info.name.strip_prefix(prefix) {
26                 assert!(name.starts_with(expected_prefix));
27                 assert!(name.ends_with(expected_suffix));
28                 return Some(name.to_string());
29             }
30         }
31         None
32     }
33 }
34 
35 #[derive(Debug)]
36 pub struct PrefixLinkNameParseCallback {
37     pub prefix: Option<String>,
38 }
39 
40 impl PrefixLinkNameParseCallback {
new(prefix: &str) -> Self41     pub fn new(prefix: &str) -> Self {
42         PrefixLinkNameParseCallback {
43             prefix: Some(prefix.to_string()),
44         }
45     }
46 }
47 
48 impl ParseCallbacks for PrefixLinkNameParseCallback {
generated_link_name_override( &self, item_info: ItemInfo, ) -> Option<String>49     fn generated_link_name_override(
50         &self,
51         item_info: ItemInfo,
52     ) -> Option<String> {
53         self.prefix
54             .as_deref()
55             .map(|prefix| format!("{}{}", prefix, item_info.name))
56     }
57 }
58 
59 #[derive(Debug)]
60 struct EnumVariantRename;
61 
62 impl ParseCallbacks for EnumVariantRename {
enum_variant_name( &self, _enum_name: Option<&str>, original_variant_name: &str, _variant_value: EnumVariantValue, ) -> Option<String>63     fn enum_variant_name(
64         &self,
65         _enum_name: Option<&str>,
66         original_variant_name: &str,
67         _variant_value: EnumVariantValue,
68     ) -> Option<String> {
69         Some(format!("RENAMED_{}", original_variant_name))
70     }
71 }
72 
73 #[derive(Debug)]
74 struct BlocklistedTypeImplementsTrait;
75 
76 impl ParseCallbacks for BlocklistedTypeImplementsTrait {
blocklisted_type_implements_trait( &self, _name: &str, derive_trait: DeriveTrait, ) -> Option<ImplementsTrait>77     fn blocklisted_type_implements_trait(
78         &self,
79         _name: &str,
80         derive_trait: DeriveTrait,
81     ) -> Option<ImplementsTrait> {
82         if derive_trait == DeriveTrait::Hash {
83             Some(ImplementsTrait::No)
84         } else {
85             Some(ImplementsTrait::Yes)
86         }
87     }
88 }
89 
90 #[derive(Debug)]
91 struct FieldVisibility {
92     default: FieldVisibilityKind,
93 }
94 
95 /// Implements the `field_visibility` function of the trait by checking if the
96 /// field name starts with `private_`. If it does it makes it private, if it
97 /// doesn't it makes it public, taking into account the default visibility.
98 impl ParseCallbacks for FieldVisibility {
99     fn field_visibility(
100         &self,
101         FieldInfo { field_name, .. }: FieldInfo,
102     ) -> Option<FieldVisibilityKind> {
103         match (self.default, field_name.starts_with("private_")) {
104             (FieldVisibilityKind::Private, false) => {
105                 Some(FieldVisibilityKind::Public)
106             }
107             (FieldVisibilityKind::Public, true) => {
108                 Some(FieldVisibilityKind::Private)
109             }
110             (FieldVisibilityKind::PublicCrate, _) => unimplemented!(),
111             _ => None,
112         }
113     }
114 }
115 
116 #[derive(Debug)]
117 pub(super) struct WrapAsVariadicFn;
118 
119 impl ParseCallbacks for WrapAsVariadicFn {
wrap_as_variadic_fn(&self, name: &str) -> Option<String>120     fn wrap_as_variadic_fn(&self, name: &str) -> Option<String> {
121         Some(name.to_owned() + "_wrapped")
122     }
123 }
124 
lookup(cb: &str) -> Box<dyn ParseCallbacks>125 pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
126     match cb {
127         "enum-variant-rename" => Box::new(EnumVariantRename),
128         "blocklisted-type-implements-trait" => {
129             Box::new(BlocklistedTypeImplementsTrait)
130         }
131         "wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn),
132         call_back => {
133             if let Some(prefix) =
134                 call_back.strip_prefix("remove-function-prefix-")
135             {
136                 let lnopc = RemovePrefixParseCallback::new(prefix);
137                 Box::new(lnopc)
138             } else if let Some(prefix) =
139                 call_back.strip_prefix("prefix-link-name-")
140             {
141                 let plnpc = PrefixLinkNameParseCallback::new(prefix);
142                 Box::new(plnpc)
143             } else if let Some(default) =
144                 call_back.strip_prefix("field-visibility-default-")
145             {
146                 Box::new(FieldVisibility {
147                     default: default.parse().expect(
148                         "unable to parse field-visibility-default callback",
149                     ),
150                 })
151             } else {
152                 panic!("Couldn't find name ParseCallbacks: {}", cb)
153             }
154         }
155     }
156 }
157