1use std::io::Write;
2
3use crate::callbacks::IntKind;
4
5use crate::ir::comp::CompKind;
6use crate::ir::context::{BindgenContext, TypeId};
7use crate::ir::function::{Function, FunctionKind};
8use crate::ir::item::Item;
9use crate::ir::item::ItemCanonicalName;
10use crate::ir::item_kind::ItemKind;
11use crate::ir::ty::{FloatKind, Type, TypeKind};
12
13use super::{CodegenError, WrapAsVariadic};
14
15fn get_loc(item: &Item) -> String {
16 itemOption.location()
17 .map(|x: &SourceLocation| x.to_string())
18 .unwrap_or_else(|| "unknown".to_owned())
19}
20
21pub(super) trait CSerialize<'a> {
22 type Extra;
23
24 fn serialize<W: Write>(
25 &self,
26 ctx: &BindgenContext,
27 extra: Self::Extra,
28 stack: &mut Vec<String>,
29 writer: &mut W,
30 ) -> Result<(), CodegenError>;
31}
32
33impl<'a> CSerialize<'a> for Item {
34 type Extra = &'a Option<WrapAsVariadic>;
35
36 fn serialize<W: Write>(
37 &self,
38 ctx: &BindgenContext,
39 extra: Self::Extra,
40 stack: &mut Vec<String>,
41 writer: &mut W,
42 ) -> Result<(), CodegenError> {
43 match self.kind() {
44 ItemKind::Function(func: &Function) => {
45 func.serialize(ctx, (self, extra), stack, writer)
46 }
47 kind: &ItemKind => Err(CodegenError::Serialize {
48 msg: format!("Cannot serialize item kind {:?}", kind),
49 loc: get_loc(self),
50 }),
51 }
52 }
53}
54
55impl<'a> CSerialize<'a> for Function {
56 type Extra = (&'a Item, &'a Option<WrapAsVariadic>);
57
58 fn serialize<W: Write>(
59 &self,
60 ctx: &BindgenContext,
61 (item, wrap_as_variadic): Self::Extra,
62 stack: &mut Vec<String>,
63 writer: &mut W,
64 ) -> Result<(), CodegenError> {
65 if self.kind() != FunctionKind::Function {
66 return Err(CodegenError::Serialize {
67 msg: format!(
68 "Cannot serialize function kind {:?}",
69 self.kind(),
70 ),
71 loc: get_loc(item),
72 });
73 }
74
75 let signature = match ctx.resolve_type(self.signature()).kind() {
76 TypeKind::Function(signature) => signature,
77 _ => unreachable!(),
78 };
79
80 assert!(!signature.is_variadic());
81
82 let name = self.name();
83
84 // Function argoments stored as `(name, type_id)` tuples.
85 let args = {
86 let mut count = 0;
87
88 let idx_to_prune = wrap_as_variadic.as_ref().map(
89 |WrapAsVariadic {
90 idx_of_va_list_arg, ..
91 }| *idx_of_va_list_arg,
92 );
93
94 signature
95 .argument_types()
96 .iter()
97 .cloned()
98 .enumerate()
99 .filter_map(|(idx, (opt_name, type_id))| {
100 if Some(idx) == idx_to_prune {
101 None
102 } else {
103 Some((
104 opt_name.unwrap_or_else(|| {
105 let name = format!("arg_{}", count);
106 count += 1;
107 name
108 }),
109 type_id,
110 ))
111 }
112 })
113 .collect::<Vec<_>>()
114 };
115
116 // The name used for the wrapper self.
117 let wrap_name = format!("{}{}", name, ctx.wrap_static_fns_suffix());
118
119 // The function's return type
120 let (ret_item, ret_ty) = {
121 let type_id = signature.return_type();
122 let ret_item = ctx.resolve_item(type_id);
123 let ret_ty = ret_item.expect_type();
124
125 // Write `ret_ty`.
126 ret_ty.serialize(ctx, ret_item, stack, writer)?;
127
128 (ret_item, ret_ty)
129 };
130
131 const INDENT: &str = " ";
132
133 // Write `wrap_name(args`.
134 write!(writer, " {}(", wrap_name)?;
135 serialize_args(&args, ctx, writer)?;
136
137 if wrap_as_variadic.is_none() {
138 // Write `) { name(` if the function returns void and `) { return name(` if it does not.
139 if ret_ty.is_void() {
140 write!(writer, ") {{ {}(", name)?;
141 } else {
142 write!(writer, ") {{ return {}(", name)?;
143 }
144 } else {
145 // Write `, ...) {`
146 writeln!(writer, ", ...) {{")?;
147
148 // Declare the return type `RET_TY ret;` if their is a need to do so
149 if !ret_ty.is_void() {
150 write!(writer, "{INDENT}")?;
151 ret_ty.serialize(ctx, ret_item, stack, writer)?;
152 writeln!(writer, " ret;")?;
153 }
154
155 // Setup va_list
156 writeln!(writer, "{INDENT}va_list ap;\n")?;
157 writeln!(
158 writer,
159 "{INDENT}va_start(ap, {});",
160 args.last().unwrap().0
161 )?;
162
163 write!(writer, "{INDENT}")?;
164 // Write `ret = name(` or `name(` depending if the function returns something
165 if !ret_ty.is_void() {
166 write!(writer, "ret = ")?;
167 }
168 write!(writer, "{}(", name)?;
169 }
170
171 // Get the arguments names and insert at the right place if necessary `ap`
172 let mut args: Vec<_> = args.into_iter().map(|(name, _)| name).collect();
173 if let Some(WrapAsVariadic {
174 idx_of_va_list_arg, ..
175 }) = wrap_as_variadic
176 {
177 args.insert(*idx_of_va_list_arg, "ap".to_owned());
178 }
179
180 // Write `arg_names);`.
181 serialize_sep(", ", args.iter(), ctx, writer, |name, _, buf| {
182 write!(buf, "{}", name).map_err(From::from)
183 })?;
184 #[rustfmt::skip]
185 write!(writer, ");{}", if wrap_as_variadic.is_none() { " " } else { "\n" })?;
186
187 if wrap_as_variadic.is_some() {
188 // End va_list and return the result if their is one
189 writeln!(writer, "{INDENT}va_end(ap);")?;
190 if !ret_ty.is_void() {
191 writeln!(writer, "{INDENT}return ret;")?;
192 }
193 }
194
195 writeln!(writer, "}}")?;
196
197 Ok(())
198 }
199}
200
201impl<'a> CSerialize<'a> for TypeId {
202 type Extra = ();
203
204 fn serialize<W: Write>(
205 &self,
206 ctx: &BindgenContext,
207 (): Self::Extra,
208 stack: &mut Vec<String>,
209 writer: &mut W,
210 ) -> Result<(), CodegenError> {
211 let item: &Item = ctx.resolve_item(*self);
212 item.expect_type().serialize(ctx, extra:item, stack, writer)
213 }
214}
215
216impl<'a> CSerialize<'a> for Type {
217 type Extra = &'a Item;
218
219 fn serialize<W: Write>(
220 &self,
221 ctx: &BindgenContext,
222 item: Self::Extra,
223 stack: &mut Vec<String>,
224 writer: &mut W,
225 ) -> Result<(), CodegenError> {
226 match self.kind() {
227 TypeKind::Void => {
228 if self.is_const() {
229 write!(writer, "const ")?;
230 }
231 write!(writer, "void")?
232 }
233 TypeKind::NullPtr => {
234 if self.is_const() {
235 write!(writer, "const ")?;
236 }
237 write!(writer, "nullptr_t")?
238 }
239 TypeKind::Int(int_kind) => {
240 if self.is_const() {
241 write!(writer, "const ")?;
242 }
243 match int_kind {
244 IntKind::Bool => write!(writer, "bool")?,
245 IntKind::SChar => write!(writer, "signed char")?,
246 IntKind::UChar => write!(writer, "unsigned char")?,
247 IntKind::WChar => write!(writer, "wchar_t")?,
248 IntKind::Short => write!(writer, "short")?,
249 IntKind::UShort => write!(writer, "unsigned short")?,
250 IntKind::Int => write!(writer, "int")?,
251 IntKind::UInt => write!(writer, "unsigned int")?,
252 IntKind::Long => write!(writer, "long")?,
253 IntKind::ULong => write!(writer, "unsigned long")?,
254 IntKind::LongLong => write!(writer, "long long")?,
255 IntKind::ULongLong => write!(writer, "unsigned long long")?,
256 IntKind::Char { .. } => write!(writer, "char")?,
257 int_kind => {
258 return Err(CodegenError::Serialize {
259 msg: format!(
260 "Cannot serialize integer kind {:?}",
261 int_kind
262 ),
263 loc: get_loc(item),
264 })
265 }
266 }
267 }
268 TypeKind::Float(float_kind) => {
269 if self.is_const() {
270 write!(writer, "const ")?;
271 }
272 match float_kind {
273 FloatKind::Float16 => write!(writer, "_Float16")?,
274 FloatKind::Float => write!(writer, "float")?,
275 FloatKind::Double => write!(writer, "double")?,
276 FloatKind::LongDouble => write!(writer, "long double")?,
277 FloatKind::Float128 => write!(writer, "__float128")?,
278 }
279 }
280 TypeKind::Complex(float_kind) => {
281 if self.is_const() {
282 write!(writer, "const ")?;
283 }
284 match float_kind {
285 FloatKind::Float16 => write!(writer, "_Float16 complex")?,
286 FloatKind::Float => write!(writer, "float complex")?,
287 FloatKind::Double => write!(writer, "double complex")?,
288 FloatKind::LongDouble => {
289 write!(writer, "long double complex")?
290 }
291 FloatKind::Float128 => write!(writer, "__complex128")?,
292 }
293 }
294 TypeKind::Alias(type_id) => {
295 if let Some(name) = self.name() {
296 if self.is_const() {
297 write!(writer, "const {}", name)?;
298 } else {
299 write!(writer, "{}", name)?;
300 }
301 } else {
302 type_id.serialize(ctx, (), stack, writer)?;
303 }
304 }
305 TypeKind::Array(type_id, length) => {
306 type_id.serialize(ctx, (), stack, writer)?;
307 write!(writer, " [{}]", length)?
308 }
309 TypeKind::Function(signature) => {
310 if self.is_const() {
311 stack.push("const ".to_string());
312 }
313
314 signature.return_type().serialize(
315 ctx,
316 (),
317 &mut vec![],
318 writer,
319 )?;
320
321 write!(writer, " (")?;
322 while let Some(item) = stack.pop() {
323 write!(writer, "{}", item)?;
324 }
325 write!(writer, ")")?;
326
327 let args = signature.argument_types();
328 if args.is_empty() {
329 write!(writer, " (void)")?;
330 } else {
331 write!(writer, " (")?;
332 serialize_sep(
333 ", ",
334 args.iter(),
335 ctx,
336 writer,
337 |(name, type_id), ctx, buf| {
338 let mut stack = vec![];
339 if let Some(name) = name {
340 stack.push(name.clone());
341 }
342 type_id.serialize(ctx, (), &mut stack, buf)
343 },
344 )?;
345 write!(writer, ")")?
346 }
347 }
348 TypeKind::ResolvedTypeRef(type_id) => {
349 if self.is_const() {
350 write!(writer, "const ")?;
351 }
352 type_id.serialize(ctx, (), stack, writer)?
353 }
354 TypeKind::Pointer(type_id) => {
355 if self.is_const() {
356 stack.push("*const ".to_owned());
357 } else {
358 stack.push("*".to_owned());
359 }
360 type_id.serialize(ctx, (), stack, writer)?
361 }
362 TypeKind::Comp(comp_info) => {
363 if self.is_const() {
364 write!(writer, "const ")?;
365 }
366
367 let name = item.canonical_name(ctx);
368
369 match comp_info.kind() {
370 CompKind::Struct => write!(writer, "struct {}", name)?,
371 CompKind::Union => write!(writer, "union {}", name)?,
372 };
373 }
374 TypeKind::Enum(_enum_ty) => {
375 if self.is_const() {
376 write!(writer, "const ")?;
377 }
378
379 let name = item.canonical_name(ctx);
380 write!(writer, "enum {}", name)?;
381 }
382 ty => {
383 return Err(CodegenError::Serialize {
384 msg: format!("Cannot serialize type kind {:?}", ty),
385 loc: get_loc(item),
386 })
387 }
388 };
389
390 if !stack.is_empty() {
391 write!(writer, " ")?;
392 while let Some(item) = stack.pop() {
393 write!(writer, "{}", item)?;
394 }
395 }
396
397 Ok(())
398 }
399}
400
401fn serialize_args<W: Write>(
402 args: &[(String, TypeId)],
403 ctx: &BindgenContext,
404 writer: &mut W,
405) -> Result<(), CodegenError> {
406 if args.is_empty() {
407 write!(writer, "void")?;
408 } else {
409 serialize_sep(
410 sep:", ",
411 args.iter(),
412 ctx,
413 buf:writer,
414 |(name: &String, type_id: &TypeId), ctx: &BindgenContext, buf: &mut W| {
415 type_id.serialize(ctx, (), &mut vec![name.clone()], writer:buf)
416 },
417 )?;
418 }
419
420 Ok(())
421}
422
423fn serialize_sep<
424 W: Write,
425 F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
426 I: Iterator,
427>(
428 sep: &str,
429 mut iter: I,
430 ctx: &BindgenContext,
431 buf: &mut W,
432 mut f: F,
433) -> Result<(), CodegenError> {
434 if let Some(item: ::Item) = iter.next() {
435 f(item, ctx, buf)?;
436 let sep: &[u8] = sep.as_bytes();
437 for item: ::Item in iter {
438 buf.write_all(buf:sep)?;
439 f(item, ctx, buf)?;
440 }
441 }
442
443 Ok(())
444}
445