1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use crate::bindgen::config::MangleConfig;
6 use crate::bindgen::ir::{Path, Type};
7 use crate::bindgen::rename::IdentifierType;
8 
mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path9 pub fn mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path {
10     Path::new(mangle_name(path.name(), generic_values, config))
11 }
12 
mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String13 pub fn mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String {
14     Mangler::new(name, generic_values, /* last = */ true, config).mangle()
15 }
16 
17 enum Separator {
18     OpeningAngleBracket = 1,
19     Comma,
20     ClosingAngleBracket,
21     BeginMutPtr,
22     BeginConstPtr,
23     BeginFn,
24     BetweenFnArg,
25     EndFn,
26 }
27 
28 struct Mangler<'a> {
29     input: &'a str,
30     generic_values: &'a [Type],
31     output: String,
32     last: bool,
33     config: &'a MangleConfig,
34 }
35 
36 impl<'a> Mangler<'a> {
new( input: &'a str, generic_values: &'a [Type], last: bool, config: &'a MangleConfig, ) -> Self37     fn new(
38         input: &'a str,
39         generic_values: &'a [Type],
40         last: bool,
41         config: &'a MangleConfig,
42     ) -> Self {
43         Self {
44             input,
45             generic_values,
46             output: String::new(),
47             last,
48             config,
49         }
50     }
51 
mangle(mut self) -> String52     fn mangle(mut self) -> String {
53         self.mangle_internal();
54         self.output
55     }
56 
push(&mut self, id: Separator)57     fn push(&mut self, id: Separator) {
58         let count = id as usize;
59         let separator = if self.config.remove_underscores {
60             ""
61         } else {
62             "_"
63         };
64         self.output.extend(std::iter::repeat(separator).take(count));
65     }
66 
append_mangled_type(&mut self, ty: &Type, last: bool)67     fn append_mangled_type(&mut self, ty: &Type, last: bool) {
68         match *ty {
69             Type::Path(ref generic) => {
70                 let sub_path =
71                     Mangler::new(generic.export_name(), generic.generics(), last, self.config)
72                         .mangle();
73 
74                 self.output.push_str(
75                     &self
76                         .config
77                         .rename_types
78                         .apply(&sub_path, IdentifierType::Type),
79                 );
80             }
81             Type::Primitive(ref primitive) => {
82                 self.output.push_str(
83                     &self
84                         .config
85                         .rename_types
86                         .apply(primitive.to_repr_rust(), IdentifierType::Type),
87                 );
88             }
89             Type::Ptr {
90                 ref ty, is_const, ..
91             } => {
92                 self.push(if is_const {
93                     Separator::BeginConstPtr
94                 } else {
95                     Separator::BeginMutPtr
96                 });
97                 self.append_mangled_type(&**ty, last);
98             }
99             Type::FuncPtr {
100                 ref ret, ref args, ..
101             } => {
102                 self.push(Separator::BeginFn);
103                 self.append_mangled_type(&**ret, args.is_empty());
104                 for (i, arg) in args.iter().enumerate() {
105                     self.push(Separator::BetweenFnArg);
106                     let last = last && i == args.len() - 1;
107                     self.append_mangled_type(&arg.1, last);
108                 }
109                 if !self.last {
110                     self.push(Separator::EndFn);
111                 }
112             }
113             Type::Array(..) => {
114                 unimplemented!(
115                     "Unable to mangle generic parameter {:?} for '{}'",
116                     ty,
117                     self.input
118                 );
119             }
120         }
121     }
122 
mangle_internal(&mut self)123     fn mangle_internal(&mut self) {
124         debug_assert!(self.output.is_empty());
125         self.output = self.input.to_owned();
126         if self.generic_values.is_empty() {
127             return;
128         }
129 
130         self.push(Separator::OpeningAngleBracket);
131         for (i, ty) in self.generic_values.iter().enumerate() {
132             if i != 0 {
133                 self.push(Separator::Comma);
134             }
135             let last = self.last && i == self.generic_values.len() - 1;
136             self.append_mangled_type(ty, last);
137         }
138 
139         // Skip writing the trailing '>' mangling when possible
140         if !self.last {
141             self.push(Separator::ClosingAngleBracket)
142         }
143     }
144 }
145 
146 #[test]
generics()147 fn generics() {
148     use crate::bindgen::ir::{GenericPath, PrimitiveType};
149     use crate::bindgen::rename::RenameRule::{self, PascalCase};
150 
151     fn float() -> Type {
152         Type::Primitive(PrimitiveType::Float)
153     }
154 
155     fn c_char() -> Type {
156         Type::Primitive(PrimitiveType::Char)
157     }
158 
159     fn path(path: &str) -> Type {
160         generic_path(path, &[])
161     }
162 
163     fn generic_path(path: &str, generics: &[Type]) -> Type {
164         let path = Path::new(path);
165         let generic_path = GenericPath::new(path, generics.to_owned());
166         Type::Path(generic_path)
167     }
168 
169     // Foo<f32> => Foo_f32
170     assert_eq!(
171         mangle_path(&Path::new("Foo"), &[float()], &MangleConfig::default()),
172         Path::new("Foo_f32")
173     );
174 
175     // Foo<Bar<f32>> => Foo_Bar_f32
176     assert_eq!(
177         mangle_path(
178             &Path::new("Foo"),
179             &[generic_path("Bar", &[float()])],
180             &MangleConfig::default(),
181         ),
182         Path::new("Foo_Bar_f32")
183     );
184 
185     // Foo<Bar> => Foo_Bar
186     assert_eq!(
187         mangle_path(&Path::new("Foo"), &[path("Bar")], &MangleConfig::default()),
188         Path::new("Foo_Bar")
189     );
190 
191     // Foo<Bar> => FooBar
192     assert_eq!(
193         mangle_path(
194             &Path::new("Foo"),
195             &[path("Bar")],
196             &MangleConfig {
197                 remove_underscores: true,
198                 rename_types: RenameRule::None,
199             }
200         ),
201         Path::new("FooBar")
202     );
203 
204     // Foo<Bar<f32>> => FooBarF32
205     assert_eq!(
206         mangle_path(
207             &Path::new("Foo"),
208             &[generic_path("Bar", &[float()])],
209             &MangleConfig {
210                 remove_underscores: true,
211                 rename_types: PascalCase,
212             },
213         ),
214         Path::new("FooBarF32")
215     );
216 
217     // Foo<Bar<c_char>> => FooBarCChar
218     assert_eq!(
219         mangle_path(
220             &Path::new("Foo"),
221             &[generic_path("Bar", &[c_char()])],
222             &MangleConfig {
223                 remove_underscores: true,
224                 rename_types: PascalCase,
225             },
226         ),
227         Path::new("FooBarCChar")
228     );
229 
230     // Foo<Bar<T>> => Foo_Bar_T
231     assert_eq!(
232         mangle_path(
233             &Path::new("Foo"),
234             &[generic_path("Bar", &[path("T")])],
235             &MangleConfig::default(),
236         ),
237         Path::new("Foo_Bar_T")
238     );
239 
240     // Foo<Bar<T>, E> => Foo_Bar_T_____E
241     assert_eq!(
242         mangle_path(
243             &Path::new("Foo"),
244             &[generic_path("Bar", &[path("T")]), path("E")],
245             &MangleConfig::default(),
246         ),
247         Path::new("Foo_Bar_T_____E")
248     );
249 
250     // Foo<Bar<T>, Bar<E>> => Foo_Bar_T_____Bar_E
251     assert_eq!(
252         mangle_path(
253             &Path::new("Foo"),
254             &[
255                 generic_path("Bar", &[path("T")]),
256                 generic_path("Bar", &[path("E")]),
257             ],
258             &MangleConfig::default(),
259         ),
260         Path::new("Foo_Bar_T_____Bar_E")
261     );
262 
263     // Foo<Bar<T>, E> => FooBarTE
264     assert_eq!(
265         mangle_path(
266             &Path::new("Foo"),
267             &[generic_path("Bar", &[path("T")]), path("E")],
268             &MangleConfig {
269                 remove_underscores: true,
270                 rename_types: PascalCase,
271             },
272         ),
273         Path::new("FooBarTE")
274     );
275 
276     // Foo<Bar<T>, Bar<E>> => FooBarTBarE
277     assert_eq!(
278         mangle_path(
279             &Path::new("Foo"),
280             &[
281                 generic_path("Bar", &[path("T")]),
282                 generic_path("Bar", &[path("E")]),
283             ],
284             &MangleConfig {
285                 remove_underscores: true,
286                 rename_types: PascalCase,
287             },
288         ),
289         Path::new("FooBarTBarE")
290     );
291 }
292