diff --git a/src/analysis/function_parameters.rs b/src/analysis/function_parameters.rs index 5cd5384de..3f3e15b84 100644 --- a/src/analysis/function_parameters.rs +++ b/src/analysis/function_parameters.rs @@ -240,7 +240,12 @@ pub fn analyze( } }; - if async_func && to_remove.contains(&(pos - correction_instance)) { + if async_func + && pos + .checked_sub(correction_instance) + .map(|p| to_remove.contains(&p)) + .unwrap_or(false) + { add_rust_parameter = false; } let mut transfer = par.transfer; diff --git a/src/analysis/functions.rs b/src/analysis/functions.rs index 62313bea1..4902207fe 100644 --- a/src/analysis/functions.rs +++ b/src/analysis/functions.rs @@ -735,7 +735,12 @@ fn analyze_function( correction_instance = 1; } - if r#async && to_remove.contains(&(pos - correction_instance)) { + if r#async + && pos + .checked_sub(correction_instance) + .map(|p| to_remove.contains(&p)) + .unwrap_or(false) + { continue; } assert!( diff --git a/src/analysis/return_value.rs b/src/analysis/return_value.rs index fb9207ea2..90e51b838 100644 --- a/src/analysis/return_value.rs +++ b/src/analysis/return_value.rs @@ -122,6 +122,7 @@ pub fn analyze( let par = analysis::Parameter::from_return_value(env, lib_par, configured_functions); if let Ok(rust_type) = RustType::builder(env, typ) .direction(par.lib_par.direction) + .c_type(par.lib_par.c_type.clone()) .try_from_glib(&par.try_from_glib) .try_build() { @@ -130,6 +131,7 @@ pub fn analyze( commented = RustType::builder(env, typ) .direction(func.ret.direction) + .c_type(par.lib_par.c_type.clone()) .try_from_glib(&par.try_from_glib) .try_build_param() .is_err(); diff --git a/src/analysis/rust_type.rs b/src/analysis/rust_type.rs index 142076845..8dd23b4a8 100644 --- a/src/analysis/rust_type.rs +++ b/src/analysis/rust_type.rs @@ -191,6 +191,7 @@ pub struct RustTypeBuilder<'env> { concurrency: library::Concurrency, try_from_glib: TryFromGlib, callback_parameters_config: CallbackParameters, + c_type: String, } impl<'env> RustTypeBuilder<'env> { @@ -205,6 +206,7 @@ impl<'env> RustTypeBuilder<'env> { concurrency: library::Concurrency::None, try_from_glib: TryFromGlib::default(), callback_parameters_config: Vec::new(), + c_type: String::default(), } } @@ -238,6 +240,11 @@ impl<'env> RustTypeBuilder<'env> { self } + pub fn c_type(mut self, c_type: String) -> Self { + self.c_type = c_type; + self + } + pub fn callback_parameters_config( mut self, callback_parameters_config: &[CallbackParameter], @@ -348,7 +355,8 @@ impl<'env> RustTypeBuilder<'env> { if ConversionType::of(self.env, inner_tid) == ConversionType::Pointer => { skip_option = true; - let inner_ref_mode = match self.env.type_(inner_tid) { + let inner_type = self.env.type_(inner_tid); + let inner_ref_mode = match inner_type { Class(..) | Interface(..) => RefMode::None, Record(record) => match RecordType::of(record) { RecordType::Boxed => RefMode::None, @@ -373,7 +381,59 @@ impl<'env> RustTypeBuilder<'env> { if self.ref_mode.is_ref() { format!("[{typ}]") } else { - format!("Vec<{typ}>") + let is_obj = matches!(inner_type, Class(_) | Interface(_)); + let is_ptr = is_obj + || matches!(inner_type, Basic(Pointer)) + || (matches!(inner_type, Record(_)) + && self + .env + .config + .objects + .get(&inner_tid.full_name(&self.env.library)) + .map(|o| !o.boxed_inline) + .unwrap_or(false)); + let is_string = matches!(inner_type, Basic(Utf8)); + match *type_ { + CArray(_) if is_ptr => { + format!("{}<{typ}>", use_glib_type(self.env, "PtrSlice")) + } + CArray(_) + if is_string + && matches!( + self.c_type.as_str(), + "char**" | "gchar**" + ) => + { + use_glib_type(self.env, "StrV") + } + CArray(_) + if !matches!( + inner_type, + Basic(Utf8 | Filename | OsString | Boolean) + ) => + { + format!("{}<{typ}>", use_glib_type(self.env, "Slice")) + } + List(_) if is_ptr => { + format!("{}<{typ}>", use_glib_type(self.env, "List")) + } + List(_) if is_string => format!( + "{}<{}>", + use_glib_type(self.env, "List"), + use_glib_type(self.env, "GStringPtr") + ), + SList(_) if is_ptr => { + format!("{}<{typ}>", use_glib_type(self.env, "SList")) + } + SList(_) if is_string => format!( + "{}<{}>", + use_glib_type(self.env, "SList"), + use_glib_type(self.env, "GStringPtr") + ), + /* TODO: Handle Array and PtrArray when they gain type + * parameters */ + _ => format!("Vec<{typ}>"), + } } }) }) @@ -623,6 +683,7 @@ impl<'env> RustTypeBuilder<'env> { .direction(self.direction) .nullable(self.nullable) .ref_mode(self.ref_mode) + .c_type(self.c_type) .scope(self.scope) .try_from_glib(&self.try_from_glib) .try_build(); diff --git a/src/codegen/parameter.rs b/src/codegen/parameter.rs index efdada344..c85295612 100644 --- a/src/codegen/parameter.rs +++ b/src/codegen/parameter.rs @@ -29,6 +29,7 @@ impl ToParameter for CParameter { let type_name = RustType::builder(env, self.typ) .direction(self.direction) .nullable(self.nullable) + .c_type(self.c_type.clone()) .ref_mode(ref_mode) .scope(self.scope) .try_from_glib(&self.try_from_glib) diff --git a/src/codegen/return_value.rs b/src/codegen/return_value.rs index 42f1112ee..68e4dda7b 100644 --- a/src/codegen/return_value.rs +++ b/src/codegen/return_value.rs @@ -31,6 +31,7 @@ impl ToReturnValue for library::Parameter { .direction(self.direction) .nullable(self.nullable) .scope(self.scope) + .c_type(self.c_type.clone()) .try_from_glib(try_from_glib) .try_build_param() .into_string(); @@ -261,6 +262,7 @@ fn out_parameter_as_return(out: &analysis::Parameter, env: &Env) -> String { let name = RustType::builder(env, out.lib_par.typ) .direction(ParameterDirection::Return) .nullable(out.lib_par.nullable) + .c_type(out.lib_par.c_type.clone()) .scope(out.lib_par.scope) .try_from_glib(&out.try_from_glib) .try_build_param() diff --git a/src/codegen/translate_from_glib.rs b/src/codegen/translate_from_glib.rs index dcb81c7bc..f2e9c5f70 100644 --- a/src/codegen/translate_from_glib.rs +++ b/src/codegen/translate_from_glib.rs @@ -88,6 +88,7 @@ impl TranslateFromGlib for analysis::return_value::Info { Some(tid) => { let rust_type = RustType::builder(env, tid) .direction(par.lib_par.direction) + .c_type(par.lib_par.c_type.clone()) .try_from_glib(&par.try_from_glib) .try_build(); let from_glib_xxx = from_glib_xxx(par.lib_par.transfer, None);