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 item.location()
17 .map_or_else(|| "unknown".to_owned(), |x| x.to_string())
18}
19
20pub(super) trait CSerialize<'a> {
21 type Extra;
22
23 fn serialize<W: Write>(
24 &self,
25 ctx: &BindgenContext,
26 extra: Self::Extra,
27 stack: &mut Vec<String>,
28 writer: &mut W,
29 ) -> Result<(), CodegenError>;
30}
31
32impl<'a> CSerialize<'a> for Item {
33 type Extra = &'a Option<WrapAsVariadic>;
34
35 fn serialize<W: Write>(
36 &self,
37 ctx: &BindgenContext,
38 extra: Self::Extra,
39 stack: &mut Vec<String>,
40 writer: &mut W,
41 ) -> Result<(), CodegenError> {
42 match self.kind() {
43 ItemKind::Function(func) => {
44 func.serialize(ctx, (self, extra), stack, writer)
45 }
46 kind => Err(CodegenError::Serialize {
47 msg: format!("Cannot serialize item kind {kind:?}"),
48 loc: get_loc(self),
49 }),
50 }
51 }
52}
53
54impl<'a> CSerialize<'a> for Function {
55 type Extra = (&'a Item, &'a Option<WrapAsVariadic>);
56
57 fn serialize<W: Write>(
58 &self,
59 ctx: &BindgenContext,
60 (item, wrap_as_variadic): Self::Extra,
61 stack: &mut Vec<String>,
62 writer: &mut W,
63 ) -> Result<(), CodegenError> {
64 if self.kind() != FunctionKind::Function {
65 return Err(CodegenError::Serialize {
66 msg: format!(
67 "Cannot serialize function kind {:?}",
68 self.kind(),
69 ),
70 loc: get_loc(item),
71 });
72 }
73
74 let TypeKind::Function(signature) =
75 ctx.resolve_type(self.signature()).kind()
76 else {
77 unreachable!()
78 };
79
80 assert!(!signature.is_variadic());
81
82 let name = self.name();
83
84 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 let wrap_name = format!("{name}{}", ctx.wrap_static_fns_suffix());
118
119 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 ret_ty.serialize(ctx, ret_item, stack, writer)?;
127
128 (ret_item, ret_ty)
129 };
130
131 const INDENT: &str = " ";
132
133 write!(writer, " {wrap_name}(")?;
135 serialize_args(&args, ctx, writer)?;
136
137 if wrap_as_variadic.is_none() {
138 if ret_ty.is_void() {
140 write!(writer, ") {{ {name}(")?;
141 } else {
142 write!(writer, ") {{ return {name}(")?;
143 }
144 } else {
145 writeln!(writer, ", ...) {{")?;
147
148 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 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 if !ret_ty.is_void() {
166 write!(writer, "ret = ")?;
167 }
168 write!(writer, "{name}(")?;
169 }
170
171 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 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 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 CSerialize<'_> 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 = ctx.resolve_item(*self);
212 item.expect_type().serialize(ctx, 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 {int_kind:?}"
261 ),
262 loc: get_loc(item),
263 })
264 }
265 }
266 }
267 TypeKind::Float(float_kind) => {
268 if self.is_const() {
269 write!(writer, "const ")?;
270 }
271 match float_kind {
272 FloatKind::Float16 => write!(writer, "_Float16")?,
273 FloatKind::Float => write!(writer, "float")?,
274 FloatKind::Double => write!(writer, "double")?,
275 FloatKind::LongDouble => write!(writer, "long double")?,
276 FloatKind::Float128 => write!(writer, "__float128")?,
277 }
278 }
279 TypeKind::Complex(float_kind) => {
280 if self.is_const() {
281 write!(writer, "const ")?;
282 }
283 match float_kind {
284 FloatKind::Float16 => write!(writer, "_Float16 complex")?,
285 FloatKind::Float => write!(writer, "float complex")?,
286 FloatKind::Double => write!(writer, "double complex")?,
287 FloatKind::LongDouble => {
288 write!(writer, "long double complex")?;
289 }
290 FloatKind::Float128 => write!(writer, "__complex128")?,
291 }
292 }
293 TypeKind::Alias(type_id) => {
294 if let Some(name) = self.name() {
295 if self.is_const() {
296 write!(writer, "const {name}")?;
297 } else {
298 write!(writer, "{name}")?;
299 }
300 } else {
301 type_id.serialize(ctx, (), stack, writer)?;
302 }
303 }
304 TypeKind::Array(type_id, length) => {
305 type_id.serialize(ctx, (), stack, writer)?;
306 write!(writer, " [{length}]")?;
307 }
308 TypeKind::Function(signature) => {
309 if self.is_const() {
310 stack.push("const ".to_string());
311 }
312
313 signature.return_type().serialize(
314 ctx,
315 (),
316 &mut vec![],
317 writer,
318 )?;
319
320 write!(writer, " (")?;
321 while let Some(item) = stack.pop() {
322 write!(writer, "{item}")?;
323 }
324 write!(writer, ")")?;
325
326 let args = signature.argument_types();
327 if args.is_empty() {
328 write!(writer, " (void)")?;
329 } else {
330 write!(writer, " (")?;
331 serialize_sep(
332 ", ",
333 args.iter(),
334 ctx,
335 writer,
336 |(name, type_id), ctx, buf| {
337 let mut stack = vec![];
338 if let Some(name) = name {
339 stack.push(name.clone());
340 }
341 type_id.serialize(ctx, (), &mut stack, buf)
342 },
343 )?;
344 write!(writer, ")")?;
345 }
346 }
347 TypeKind::ResolvedTypeRef(type_id) => {
348 if self.is_const() {
349 write!(writer, "const ")?;
350 }
351 type_id.serialize(ctx, (), stack, writer)?;
352 }
353 TypeKind::Pointer(type_id) => {
354 if self.is_const() {
355 stack.push("*const ".to_owned());
356 } else {
357 stack.push("*".to_owned());
358 }
359 type_id.serialize(ctx, (), stack, writer)?;
360 }
361 TypeKind::Comp(comp_info) => {
362 if self.is_const() {
363 write!(writer, "const ")?;
364 }
365
366 let name = item.canonical_name(ctx);
367
368 match comp_info.kind() {
369 CompKind::Struct => write!(writer, "struct {name}")?,
370 CompKind::Union => write!(writer, "union {name}")?,
371 };
372 }
373 TypeKind::Enum(_enum_ty) => {
374 if self.is_const() {
375 write!(writer, "const ")?;
376 }
377
378 let name = item.canonical_name(ctx);
379 write!(writer, "enum {name}")?;
380 }
381 ty => {
382 return Err(CodegenError::Serialize {
383 msg: format!("Cannot serialize type kind {ty:?}"),
384 loc: get_loc(item),
385 })
386 }
387 };
388
389 if !stack.is_empty() {
390 write!(writer, " ")?;
391 while let Some(item) = stack.pop() {
392 write!(writer, "{item}")?;
393 }
394 }
395
396 Ok(())
397 }
398}
399
400fn serialize_args<W: Write>(
401 args: &[(String, TypeId)],
402 ctx: &BindgenContext,
403 writer: &mut W,
404) -> Result<(), CodegenError> {
405 if args.is_empty() {
406 write!(writer, "void")?;
407 } else {
408 serialize_sep(
409 ", ",
410 args.iter(),
411 ctx,
412 writer,
413 |(name, type_id), ctx, buf| {
414 type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
415 },
416 )?;
417 }
418
419 Ok(())
420}
421
422fn serialize_sep<
423 W: Write,
424 F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
425 I: Iterator,
426>(
427 sep: &str,
428 mut iter: I,
429 ctx: &BindgenContext,
430 buf: &mut W,
431 mut f: F,
432) -> Result<(), CodegenError> {
433 if let Some(item) = iter.next() {
434 f(item, ctx, buf)?;
435 let sep = sep.as_bytes();
436 for item in iter {
437 buf.write_all(sep)?;
438 f(item, ctx, buf)?;
439 }
440 }
441
442 Ok(())
443}