use std::io::Write;
use crate ::callbacks::IntKind;
use crate ::ir::comp::CompKind;
use crate ::ir::context::{BindgenContext, TypeId};
use crate ::ir::function::{Function, FunctionKind};
use crate ::ir::item::Item;
use crate ::ir::item::ItemCanonicalName;
use crate ::ir::item_kind::ItemKind;
use crate ::ir::ty::{FloatKind, Type , TypeKind};
use super ::{CodegenError, WrapAsVariadic};
fn get_loc(item: &Item) -> String {
item.location()
.map(|x| x.to_string())
.unwrap_or_else(|| "unknown" .to_owned())
}
pub (super ) trait CSerialize<'a> {
type Extra;
fn serialize<W: Write>(
&self ,
ctx: &BindgenContext,
extra: Self ::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError>;
}
impl <'a> CSerialize<' a> for Item {
type Extra = &'a Option<WrapAsVariadic>;
fn serialize<W: Write>(
&self ,
ctx: &BindgenContext,
extra: Self ::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError> {
match self .kind() {
ItemKind::Function(func) => {
func.serialize(ctx, (self , extra), stack, writer)
}
kind => Err(CodegenError::Serialize {
msg: format!("Cannot serialize item kind {:?}" , kind),
loc: get_loc(self ),
}),
}
}
}
impl <'a> CSerialize<' a> for Function {
type Extra = (&'a Item, &' a Option<WrapAsVariadic>);
fn serialize<W: Write>(
&self ,
ctx: &BindgenContext,
(item, wrap_as_variadic): Self ::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError> {
if self .kind() != FunctionKind::Function {
return Err(CodegenError::Serialize {
msg: format!(
"Cannot serialize function kind {:?}" ,
self .kind(),
),
loc: get_loc(item),
});
}
let signature = match ctx.resolve_type(self .signature()).kind() {
TypeKind::Function(signature) => signature,
_ => unreachable!(),
};
assert!(!signature.is_variadic());
let name = self .name();
// Function argoments stored as `(name, type_id)` tuples.
let args = {
let mut count = 0 ;
let idx_to_prune = wrap_as_variadic.as_ref().map(
|WrapAsVariadic {
idx_of_va_list_arg, ..
}| *idx_of_va_list_arg,
);
signature
.argument_types()
.iter()
.cloned()
.enumerate()
.filter_map(|(idx, (opt_name, type_id))| {
if Some(idx) == idx_to_prune {
None
} else {
Some((
opt_name.unwrap_or_else(|| {
let name = format!("arg_{}" , count);
count += 1 ;
name
}),
type_id,
))
}
})
.collect::<Vec<_>>()
};
// The name used for the wrapper self.
let wrap_name = format!("{}{}" , name, ctx.wrap_static_fns_suffix());
// The function's return type
let (ret_item, ret_ty) = {
let type_id = signature.return_type();
let ret_item = ctx.resolve_item(type_id);
let ret_ty = ret_item.expect_type();
// Write `ret_ty`.
ret_ty.serialize(ctx, ret_item, stack, writer)?;
(ret_item, ret_ty)
};
const INDENT: &str = " " ;
// Write `wrap_name(args`.
write!(writer, " {}(" , wrap_name)?;
serialize_args(&args, ctx, writer)?;
if wrap_as_variadic.is_none() {
// Write `) { name(` if the function returns void and `) { return name(` if it does not.
if ret_ty.is_void() {
write!(writer, ") {{ {}(" , name)?;
} else {
write!(writer, ") {{ return {}(" , name)?;
}
} else {
// Write `, ...) {`
writeln!(writer, ", ...) {{" )?;
// Declare the return type `RET_TY ret;` if their is a need to do so
if !ret_ty.is_void() {
write!(writer, "{INDENT}" )?;
ret_ty.serialize(ctx, ret_item, stack, writer)?;
writeln!(writer, " ret;" )?;
}
// Setup va_list
writeln!(writer, "{INDENT}va_list ap;\n" )?;
writeln!(
writer,
"{INDENT}va_start(ap, {});" ,
args.last().unwrap().0
)?;
write!(writer, "{INDENT}" )?;
// Write `ret = name(` or `name(` depending if the function returns something
if !ret_ty.is_void() {
write!(writer, "ret = " )?;
}
write!(writer, "{}(" , name)?;
}
// Get the arguments names and insert at the right place if necessary `ap`
let mut args: Vec<_> = args.into_iter().map(|(name, _)| name).collect();
if let Some(WrapAsVariadic {
idx_of_va_list_arg, ..
}) = wrap_as_variadic
{
args.insert(*idx_of_va_list_arg, "ap" .to_owned());
}
// Write `arg_names);`.
serialize_sep(", " , args.iter(), ctx, writer, |name, _, buf| {
write!(buf, "{}" , name).map_err(From::from)
})?;
#[ rustfmt::skip]
write!(writer, ");{}" , if wrap_as_variadic.is_none() { " " } else { "\n" })?;
if wrap_as_variadic.is_some() {
// End va_list and return the result if their is one
writeln!(writer, "{INDENT}va_end(ap);" )?;
if !ret_ty.is_void() {
writeln!(writer, "{INDENT}return ret;" )?;
}
}
writeln!(writer, "}}" )?;
Ok(())
}
}
impl <'a> CSerialize<' a> for TypeId {
type Extra = ();
fn serialize<W: Write>(
&self ,
ctx: &BindgenContext,
(): Self ::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError> {
let item = ctx.resolve_item(*self );
item.expect_type().serialize(ctx, item, stack, writer)
}
}
impl <'a> CSerialize<' a> for Type {
type Extra = &'a Item;
fn serialize<W: Write>(
&self ,
ctx: &BindgenContext,
item: Self ::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError> {
match self .kind() {
TypeKind::Void => {
if self .is_const() {
write!(writer, "const " )?;
}
write!(writer, "void" )?
}
TypeKind::NullPtr => {
if self .is_const() {
write!(writer, "const " )?;
}
write!(writer, "nullptr_t" )?
}
TypeKind::Int(int_kind) => {
if self .is_const() {
write!(writer, "const " )?;
}
match int_kind {
IntKind::Bool => write!(writer, "bool" )?,
IntKind::SChar => write!(writer, "signed char" )?,
IntKind::UChar => write!(writer, "unsigned char" )?,
IntKind::WChar => write!(writer, "wchar_t" )?,
IntKind::Short => write!(writer, "short" )?,
IntKind::UShort => write!(writer, "unsigned short" )?,
IntKind::Int => write!(writer, "int" )?,
IntKind::UInt => write!(writer, "unsigned int" )?,
IntKind::Long => write!(writer, "long" )?,
IntKind::ULong => write!(writer, "unsigned long" )?,
IntKind::LongLong => write!(writer, "long long" )?,
IntKind::ULongLong => write!(writer, "unsigned long long" )?,
IntKind::Char { .. } => write!(writer, "char" )?,
int_kind => {
return Err(CodegenError::Serialize {
msg: format!(
"Cannot serialize integer kind {:?}" ,
int_kind
),
loc: get_loc(item),
})
}
}
}
TypeKind::Float(float_kind) => {
if self .is_const() {
write!(writer, "const " )?;
}
match float_kind {
FloatKind::Float16 => write!(writer, "_Float16" )?,
FloatKind::Float => write!(writer, "float" )?,
FloatKind::Double => write!(writer, "double" )?,
FloatKind::LongDouble => write!(writer, "long double" )?,
FloatKind::Float128 => write!(writer, "__float128" )?,
}
}
TypeKind::Complex(float_kind) => {
if self .is_const() {
write!(writer, "const " )?;
}
match float_kind {
FloatKind::Float16 => write!(writer, "_Float16 complex" )?,
FloatKind::Float => write!(writer, "float complex" )?,
FloatKind::Double => write!(writer, "double complex" )?,
FloatKind::LongDouble => {
write!(writer, "long double complex" )?
}
FloatKind::Float128 => write!(writer, "__complex128" )?,
}
}
TypeKind::Alias(type_id) => {
if let Some(name) = self .name() {
if self .is_const() {
write!(writer, "const {}" , name)?;
} else {
write!(writer, "{}" , name)?;
}
} else {
type_id.serialize(ctx, (), stack, writer)?;
}
}
TypeKind::Array(type_id, length) => {
type_id.serialize(ctx, (), stack, writer)?;
write!(writer, " [{}]" , length)?
}
TypeKind::Function(signature) => {
if self .is_const() {
stack.push("const " .to_string());
}
signature.return_type().serialize(
ctx,
(),
&mut vec![],
writer,
)?;
write!(writer, " (" )?;
while let Some(item) = stack.pop() {
write!(writer, "{}" , item)?;
}
write!(writer, ")" )?;
let args = signature.argument_types();
if args.is_empty() {
write!(writer, " (void)" )?;
} else {
write!(writer, " (" )?;
serialize_sep(
", " ,
args.iter(),
ctx,
writer,
|(name, type_id), ctx, buf| {
let mut stack = vec![];
if let Some(name) = name {
stack.push(name.clone());
}
type_id.serialize(ctx, (), &mut stack, buf)
},
)?;
write!(writer, ")" )?
}
}
TypeKind::ResolvedTypeRef(type_id) => {
if self .is_const() {
write!(writer, "const " )?;
}
type_id.serialize(ctx, (), stack, writer)?
}
TypeKind::Pointer(type_id) => {
if self .is_const() {
stack.push("*const " .to_owned());
} else {
stack.push("*" .to_owned());
}
type_id.serialize(ctx, (), stack, writer)?
}
TypeKind::Comp(comp_info) => {
if self .is_const() {
write!(writer, "const " )?;
}
let name = item.canonical_name(ctx);
match comp_info.kind() {
CompKind::Struct => write!(writer, "struct {}" , name)?,
CompKind::Union => write!(writer, "union {}" , name)?,
};
}
TypeKind::Enum (_enum_ty) => {
if self .is_const() {
write!(writer, "const " )?;
}
let name = item.canonical_name(ctx);
write!(writer, "enum {}" , name)?;
}
ty => {
return Err(CodegenError::Serialize {
msg: format!("Cannot serialize type kind {:?}" , ty),
loc: get_loc(item),
})
}
};
if !stack.is_empty() {
write!(writer, " " )?;
while let Some(item) = stack.pop() {
write!(writer, "{}" , item)?;
}
}
Ok(())
}
}
fn serialize_args<W: Write>(
args: &[(String, TypeId)],
ctx: &BindgenContext,
writer: &mut W,
) -> Result<(), CodegenError> {
if args.is_empty() {
write!(writer, "void" )?;
} else {
serialize_sep(
", " ,
args.iter(),
ctx,
writer,
|(name, type_id), ctx, buf| {
type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
},
)?;
}
Ok(())
}
fn serialize_sep<
W: Write,
F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
I: Iterator,
>(
sep: &str,
mut iter: I,
ctx: &BindgenContext,
buf: &mut W,
mut f: F,
) -> Result<(), CodegenError> {
if let Some(item) = iter.next() {
f(item, ctx, buf)?;
let sep = sep.as_bytes();
for item in iter {
buf.write_all(sep)?;
f(item, ctx, buf)?;
}
}
Ok(())
}
Messung V0.5 in Prozent C=97 H=93 G=94
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland