Skip to content

Commit 41f191c

Browse files
committed
analysis: Don't use IntoGStr for string params with length
Also rename the old detect_length to detect_array to make it more clear
1 parent 20c4b9a commit 41f191c

File tree

2 files changed

+63
-42
lines changed

2 files changed

+63
-42
lines changed

src/analysis/bounds.rs

+3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ impl Bounds {
9090
concurrency: Concurrency,
9191
configured_functions: &[&config::functions::Function],
9292
) -> (Option<String>, Option<CallbackInfo>) {
93+
if par.has_length && par.is_gstr(env) {
94+
return (None, None);
95+
}
9396
let type_name = RustType::builder(env, par.typ)
9497
.ref_mode(if par.move_ || future {
9598
RefMode::None

src/analysis/function_parameters.rs

+60-42
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub struct CParameter {
6363
pub transfer: library::Transfer,
6464
pub caller_allocates: bool,
6565
pub is_error: bool,
66+
pub has_length: bool,
6667
pub scope: ParameterScope,
6768
/// Index of the user data parameter associated with the callback.
6869
pub user_data_index: Option<usize>,
@@ -76,6 +77,25 @@ pub struct CParameter {
7677
pub move_: bool,
7778
}
7879

80+
impl CParameter {
81+
pub fn is_gstr(&self, env: &Env) -> bool {
82+
matches!(
83+
env.type_(self.typ),
84+
library::Type::Basic(library::Basic::Utf8)
85+
) && self.ref_mode.is_ref()
86+
}
87+
pub fn is_strv(&self, env: &Env) -> bool {
88+
if let library::Type::CArray(inner) = env.type_(self.typ) {
89+
matches!(
90+
env.type_(*inner),
91+
library::Type::Basic(library::Basic::Utf8)
92+
) && !matches!(self.c_type.as_str(), "char**" | "gchar**")
93+
} else {
94+
false
95+
}
96+
}
97+
}
98+
7999
#[derive(Clone, Debug)]
80100
pub enum TransformationType {
81101
ToGlibDirect {
@@ -288,7 +308,7 @@ pub fn analyze(
288308
array_par = array_lengths.get(&(pos as u32)).copied();
289309
}
290310
if array_par.is_none() && !disable_length_detect {
291-
array_par = detect_length(env, pos, par, function_parameters);
311+
array_par = detect_array(env, pos, par, function_parameters);
292312
}
293313
if let Some(array_par) = array_par {
294314
let mut array_name = nameutil::mangle_keywords(&array_par.name);
@@ -319,6 +339,9 @@ pub fn analyze(
319339
};
320340
parameters.transformations.push(transformation);
321341
}
342+
let has_length = par.array_length.is_some()
343+
|| (!disable_length_detect
344+
&& detect_length(env, pos, par, function_parameters).is_some());
322345

323346
let immutable = configured_parameters.iter().any(|p| p.constant);
324347
let ref_mode =
@@ -340,6 +363,7 @@ pub fn analyze(
340363
nullable,
341364
ref_mode,
342365
is_error: par.is_error,
366+
has_length,
343367
scope: par.scope,
344368
user_data_index: par.closure,
345369
destroy_index: par.destroy,
@@ -454,31 +478,22 @@ pub fn analyze(
454478
}
455479

456480
let c_par = parameters.c_parameters.last().unwrap();
457-
match env.type_(typ) {
458-
library::Type::Basic(library::Basic::Utf8) if ref_mode.is_ref() => {
459-
transformation.transformation_type = TransformationType::RunWith {
460-
name: c_par.name.clone(),
461-
func: if *c_par.nullable {
462-
nameutil::use_glib_type(env, "IntoOptionalGStr::run_with_gstr")
463-
} else {
464-
nameutil::use_glib_type(env, "IntoGStr::run_with_gstr")
465-
},
466-
inner: Box::new(transformation.transformation_type),
467-
};
468-
}
469-
library::Type::CArray(inner)
470-
if matches!(
471-
env.type_(*inner),
472-
library::Type::Basic(library::Basic::Utf8)
473-
) && !matches!(c_par.c_type.as_str(), "char**" | "gchar**") =>
474-
{
475-
transformation.transformation_type = TransformationType::RunWith {
476-
name: c_par.name.clone(),
477-
func: nameutil::use_glib_type(env, "IntoStrV::run_with_strv"),
478-
inner: Box::new(TransformationType::AsPtr(c_par.name.clone())),
479-
};
480-
}
481-
_ => {}
481+
if c_par.is_gstr(env) && !has_length {
482+
transformation.transformation_type = TransformationType::RunWith {
483+
name: c_par.name.clone(),
484+
func: if *c_par.nullable {
485+
nameutil::use_glib_type(env, "IntoOptionalGStr::run_with_gstr")
486+
} else {
487+
nameutil::use_glib_type(env, "IntoGStr::run_with_gstr")
488+
},
489+
inner: Box::new(transformation.transformation_type),
490+
};
491+
} else if c_par.is_strv(env) {
492+
transformation.transformation_type = TransformationType::RunWith {
493+
name: c_par.name.clone(),
494+
func: nameutil::use_glib_type(env, "IntoStrV::run_with_strv"),
495+
inner: Box::new(TransformationType::AsPtr(c_par.name.clone())),
496+
};
482497
}
483498

484499
parameters.transformations.push(transformation);
@@ -507,30 +522,33 @@ fn detect_length<'a>(
507522
par: &library::Parameter,
508523
parameters: &'a [library::Parameter],
509524
) -> Option<&'a library::Parameter> {
510-
if !is_length(par) {
525+
if !has_length(env, par.typ) {
511526
return None;
512527
}
513528

514-
parameters.get(pos - 1).and_then(|p| {
515-
if has_length(env, p.typ) {
516-
Some(p)
517-
} else {
518-
None
519-
}
520-
})
529+
parameters
530+
.get(pos + 1)
531+
.and_then(|p| is_length(p).then_some(p))
521532
}
522533

523-
fn is_length(par: &library::Parameter) -> bool {
524-
if par.direction != library::ParameterDirection::In {
525-
return false;
534+
fn detect_array<'a>(
535+
env: &Env,
536+
pos: usize,
537+
par: &library::Parameter,
538+
parameters: &'a [library::Parameter],
539+
) -> Option<&'a library::Parameter> {
540+
if !is_length(par) {
541+
return None;
526542
}
527543

528-
let len = par.name.len();
529-
if len >= 3 && &par.name[len - 3..len] == "len" {
530-
return true;
531-
}
544+
parameters
545+
.get(pos.checked_sub(1)?)
546+
.and_then(|p| has_length(env, p.typ).then_some(p))
547+
}
532548

533-
par.name.contains("length")
549+
fn is_length(par: &library::Parameter) -> bool {
550+
par.direction == library::ParameterDirection::In
551+
&& (par.name.ends_with("len") || par.name.contains("length"))
534552
}
535553

536554
fn has_length(env: &Env, typ: TypeId) -> bool {

0 commit comments

Comments
 (0)