Skip to content

Commit

Permalink
analysis: Don't use IntoGStr for string params with length
Browse files Browse the repository at this point in the history
Also rename the old detect_length to detect_array to make it more clear
  • Loading branch information
jf2048 committed Mar 2, 2023
1 parent 20c4b9a commit 41f191c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 42 deletions.
3 changes: 3 additions & 0 deletions src/analysis/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ impl Bounds {
concurrency: Concurrency,
configured_functions: &[&config::functions::Function],
) -> (Option<String>, Option<CallbackInfo>) {
if par.has_length && par.is_gstr(env) {
return (None, None);
}
let type_name = RustType::builder(env, par.typ)
.ref_mode(if par.move_ || future {
RefMode::None
Expand Down
102 changes: 60 additions & 42 deletions src/analysis/function_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct CParameter {
pub transfer: library::Transfer,
pub caller_allocates: bool,
pub is_error: bool,
pub has_length: bool,
pub scope: ParameterScope,
/// Index of the user data parameter associated with the callback.
pub user_data_index: Option<usize>,
Expand All @@ -76,6 +77,25 @@ pub struct CParameter {
pub move_: bool,
}

impl CParameter {
pub fn is_gstr(&self, env: &Env) -> bool {
matches!(
env.type_(self.typ),
library::Type::Basic(library::Basic::Utf8)
) && self.ref_mode.is_ref()
}
pub fn is_strv(&self, env: &Env) -> bool {
if let library::Type::CArray(inner) = env.type_(self.typ) {
matches!(
env.type_(*inner),
library::Type::Basic(library::Basic::Utf8)
) && !matches!(self.c_type.as_str(), "char**" | "gchar**")
} else {
false
}
}
}

#[derive(Clone, Debug)]
pub enum TransformationType {
ToGlibDirect {
Expand Down Expand Up @@ -288,7 +308,7 @@ pub fn analyze(
array_par = array_lengths.get(&(pos as u32)).copied();
}
if array_par.is_none() && !disable_length_detect {
array_par = detect_length(env, pos, par, function_parameters);
array_par = detect_array(env, pos, par, function_parameters);
}
if let Some(array_par) = array_par {
let mut array_name = nameutil::mangle_keywords(&array_par.name);
Expand Down Expand Up @@ -319,6 +339,9 @@ pub fn analyze(
};
parameters.transformations.push(transformation);
}
let has_length = par.array_length.is_some()
|| (!disable_length_detect
&& detect_length(env, pos, par, function_parameters).is_some());

let immutable = configured_parameters.iter().any(|p| p.constant);
let ref_mode =
Expand All @@ -340,6 +363,7 @@ pub fn analyze(
nullable,
ref_mode,
is_error: par.is_error,
has_length,
scope: par.scope,
user_data_index: par.closure,
destroy_index: par.destroy,
Expand Down Expand Up @@ -454,31 +478,22 @@ pub fn analyze(
}

let c_par = parameters.c_parameters.last().unwrap();
match env.type_(typ) {
library::Type::Basic(library::Basic::Utf8) if ref_mode.is_ref() => {
transformation.transformation_type = TransformationType::RunWith {
name: c_par.name.clone(),
func: if *c_par.nullable {
nameutil::use_glib_type(env, "IntoOptionalGStr::run_with_gstr")
} else {
nameutil::use_glib_type(env, "IntoGStr::run_with_gstr")
},
inner: Box::new(transformation.transformation_type),
};
}
library::Type::CArray(inner)
if matches!(
env.type_(*inner),
library::Type::Basic(library::Basic::Utf8)
) && !matches!(c_par.c_type.as_str(), "char**" | "gchar**") =>
{
transformation.transformation_type = TransformationType::RunWith {
name: c_par.name.clone(),
func: nameutil::use_glib_type(env, "IntoStrV::run_with_strv"),
inner: Box::new(TransformationType::AsPtr(c_par.name.clone())),
};
}
_ => {}
if c_par.is_gstr(env) && !has_length {
transformation.transformation_type = TransformationType::RunWith {
name: c_par.name.clone(),
func: if *c_par.nullable {
nameutil::use_glib_type(env, "IntoOptionalGStr::run_with_gstr")
} else {
nameutil::use_glib_type(env, "IntoGStr::run_with_gstr")
},
inner: Box::new(transformation.transformation_type),
};
} else if c_par.is_strv(env) {
transformation.transformation_type = TransformationType::RunWith {
name: c_par.name.clone(),
func: nameutil::use_glib_type(env, "IntoStrV::run_with_strv"),
inner: Box::new(TransformationType::AsPtr(c_par.name.clone())),
};
}

parameters.transformations.push(transformation);
Expand Down Expand Up @@ -507,30 +522,33 @@ fn detect_length<'a>(
par: &library::Parameter,
parameters: &'a [library::Parameter],
) -> Option<&'a library::Parameter> {
if !is_length(par) {
if !has_length(env, par.typ) {
return None;
}

parameters.get(pos - 1).and_then(|p| {
if has_length(env, p.typ) {
Some(p)
} else {
None
}
})
parameters
.get(pos + 1)
.and_then(|p| is_length(p).then_some(p))
}

fn is_length(par: &library::Parameter) -> bool {
if par.direction != library::ParameterDirection::In {
return false;
fn detect_array<'a>(
env: &Env,
pos: usize,
par: &library::Parameter,
parameters: &'a [library::Parameter],
) -> Option<&'a library::Parameter> {
if !is_length(par) {
return None;
}

let len = par.name.len();
if len >= 3 && &par.name[len - 3..len] == "len" {
return true;
}
parameters
.get(pos.checked_sub(1)?)
.and_then(|p| has_length(env, p.typ).then_some(p))
}

par.name.contains("length")
fn is_length(par: &library::Parameter) -> bool {
par.direction == library::ParameterDirection::In
&& (par.name.ends_with("len") || par.name.contains("length"))
}

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

0 comments on commit 41f191c

Please sign in to comment.