Add an annotation to represent pointers as arrays
This commit is contained in:
committed by
Emilio Cobos Álvarez
parent
73ea04c2b0
commit
ee4638ab10
+26
-2
@@ -5,7 +5,7 @@
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::declarationtyperesolver::DeclarationType;
|
||||
use crate::bindgen::ir::{Function, Type};
|
||||
use crate::bindgen::ir::{ArrayLength, Function, Type};
|
||||
use crate::bindgen::writer::{ListType, SourceWriter};
|
||||
use crate::bindgen::{Config, Language};
|
||||
|
||||
@@ -56,6 +56,25 @@ impl CDecl {
|
||||
cdecl.build_type(t, false);
|
||||
cdecl
|
||||
}
|
||||
|
||||
fn from_func_arg(t: &Type, array_length: Option<&str>) -> CDecl {
|
||||
let mut cdecl = CDecl::new();
|
||||
let length = match array_length {
|
||||
Some(l) => l,
|
||||
None => return CDecl::from_type(t),
|
||||
};
|
||||
let (ty, is_const) = match t {
|
||||
Type::Ptr { ty, is_const, .. } => (ty, is_const),
|
||||
_ => unreachable!(
|
||||
"Should never have an array length for a non pointer type {:?}",
|
||||
t
|
||||
),
|
||||
};
|
||||
let ptr_as_array = Type::Array(ty.clone(), ArrayLength::Value(length.to_string()));
|
||||
cdecl.build_type(&ptr_as_array, *is_const);
|
||||
cdecl
|
||||
}
|
||||
|
||||
fn from_func(f: &Function, layout_vertical: bool) -> CDecl {
|
||||
let mut cdecl = CDecl::new();
|
||||
cdecl.build_func(f, layout_vertical);
|
||||
@@ -66,7 +85,12 @@ impl CDecl {
|
||||
let args = f
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| (arg.name.clone(), CDecl::from_type(&arg.ty)))
|
||||
.map(|arg| {
|
||||
(
|
||||
arg.name.clone(),
|
||||
CDecl::from_func_arg(&arg.ty, arg.array_length.as_deref()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
self.declarators
|
||||
.push(CDeclarator::Func(args, layout_vertical));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::bindgen::cdecl;
|
||||
@@ -23,6 +24,7 @@ use crate::bindgen::writer::{Source, SourceWriter};
|
||||
pub struct FunctionArgument {
|
||||
pub name: Option<String>,
|
||||
pub ty: Type,
|
||||
pub array_length: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -170,7 +172,11 @@ impl Function {
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let name = arg.name.map(|n| r.apply(&n, IdentifierType::FunctionArg));
|
||||
FunctionArgument { name, ty: arg.ty }
|
||||
FunctionArgument {
|
||||
name,
|
||||
ty: arg.ty,
|
||||
array_length: None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -183,6 +189,37 @@ impl Function {
|
||||
reserved::escape(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the array length of the pointer arguments which need to use
|
||||
// the C-array notation
|
||||
if let Some(tuples) = self.annotations.list("ptrs-as-arrays") {
|
||||
let mut ptrs_as_arrays: HashMap<String, String> = HashMap::new();
|
||||
for str_tuple in tuples {
|
||||
let parts: Vec<&str> = str_tuple[1..str_tuple.len() - 1]
|
||||
.split(';')
|
||||
.map(|x| x.trim())
|
||||
.collect();
|
||||
if parts.len() != 2 {
|
||||
warn!(
|
||||
"{:?} does not follow the correct syntax, so the annotation is being ignored",
|
||||
parts
|
||||
);
|
||||
continue;
|
||||
}
|
||||
ptrs_as_arrays.insert(parts[0].to_string(), parts[1].to_string());
|
||||
}
|
||||
|
||||
for arg in &mut self.args {
|
||||
if !matches!(arg.ty, Type::Ptr { .. }) {
|
||||
continue;
|
||||
}
|
||||
let name = match arg.name {
|
||||
Some(ref name) => name,
|
||||
None => continue,
|
||||
};
|
||||
arg.array_length = ptrs_as_arrays.get(name).cloned();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,11 +374,16 @@ impl SynFnArgHelpers for syn::FnArg {
|
||||
if let Type::Array(..) = ty {
|
||||
return Err("Array as function arguments are not supported".to_owned());
|
||||
}
|
||||
Ok(Some(FunctionArgument { name, ty }))
|
||||
Ok(Some(FunctionArgument {
|
||||
name,
|
||||
ty,
|
||||
array_length: None,
|
||||
}))
|
||||
}
|
||||
syn::FnArg::Receiver(ref receiver) => Ok(Some(FunctionArgument {
|
||||
name: Some("self".to_string()),
|
||||
ty: gen_self_type(receiver),
|
||||
array_length: None,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user