Add an annotation to represent pointers as arrays

This commit is contained in:
Luni-4
2020-09-07 09:24:00 +02:00
committed by Emilio Cobos Álvarez
parent 73ea04c2b0
commit ee4638ab10
2 changed files with 70 additions and 4 deletions
+26 -2
View File
@@ -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));
+44 -2
View File
@@ -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,
})),
}
}