diff --git a/Cargo.lock b/Cargo.lock index 3c9bc60e8..fea922cb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "clock_ticks" @@ -25,18 +25,18 @@ checksum = "c49a90f58e73ac5f41ed0ac249861ceb5f0976db35fabc2b9c2c856916042d63" [[package]] name = "env_filter" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log 0.4.29", ] [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "env_filter", "log 0.4.29", @@ -74,12 +74,22 @@ dependencies = [ "env_logger", "fix-getters-rules", "getopts", + "gir-parser", "hprof", "log 0.4.29", "regex", "rustdoc-stripper", "toml", - "xml-rs", +] + +[[package]] +name = "gir-parser" +version = "0.1.4" +source = "git+https://github.com/bilelmoussaoui/gir-parser.git?rev=946d79b9d220e3c68692f3b590986a15fcca7139#946d79b9d220e3c68692f3b590986a15fcca7139" +dependencies = [ + "serde", + "xmlserde", + "xmlserde_derives", ] [[package]] @@ -125,9 +135,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "once_cell" @@ -144,6 +154,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.44" @@ -167,9 +187,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -178,9 +198,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "rustdoc-stripper" @@ -188,6 +208,16 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab2432ada69d3b404987a137436b0e475c6776f7a0c86ee00b356c0348ef40d" +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -219,9 +249,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ "proc-macro2", "quote", @@ -230,9 +260,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.11+spec-1.1.0" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", "serde_core", @@ -254,9 +284,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" dependencies = [ "winnow", ] @@ -269,9 +299,9 @@ checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-width" @@ -286,16 +316,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] -name = "xml" -version = "1.2.1" +name = "xmlserde" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8aa498d22c9bbaf482329839bc5620c46be275a19a812e9a22a2b07529a642a" +checksum = "c74aeef672aa2d8803466595ea4f8cde6873120004e0adcc7a80e399b9e48a34" +dependencies = [ + "quick-xml", +] [[package]] -name = "xml-rs" -version = "1.0.0" +name = "xmlserde_derives" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a56132a0d6ecbe77352edc10232f788fc4ceefefff4cab784a98e0e16b6b51" +checksum = "98bba6063b36ccd1151b243761dd9184b19ebf51d1514628196eb64d76bfc169" dependencies = [ - "xml", + "proc-macro2", + "quote", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 95fb84a73..628835aa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ edition = "2024" bitflags = "2.10" getopts = "0.2.24" getter_rules = { package = "fix-getters-rules", version = "0.3.0", default-features = false } -xml-rs = "1.0" toml = { version = "0.9" , features = ["preserve_order"] } env_logger = { version = "0.11", default-features = false } log = "0.4" regex = "1.12" hprof = "0.1" rustdoc-stripper = "0.1.19" +gir-parser = { git = "https://github.com/bilelmoussaoui/gir-parser.git", rev = "946d79b9d220e3c68692f3b590986a15fcca7139" } [profile.release] codegen-units = 4 diff --git a/src/analysis/bounds.rs b/src/analysis/bounds.rs index a13fa23af..fe30200e1 100644 --- a/src/analysis/bounds.rs +++ b/src/analysis/bounds.rs @@ -12,7 +12,7 @@ use crate::{ config, consts::TYPE_PARAMETERS_START, env::Env, - library::{Basic, Class, Concurrency, Function, ParameterDirection, Type, TypeId}, + library::{Basic, Class, Concurrency, Function, Type, TypeId}, traits::IntoString, }; @@ -97,16 +97,16 @@ impl Bounds { let mut ret = None; let mut need_is_into_check = false; - if !par.instance_parameter && par.direction != ParameterDirection::Out { + if !par.is_instance_parameter && !par.direction.is_out() { if let Some(bound_type) = Bounds::type_for(env, par.typ) { ret = Some(Bounds::get_to_glib_extra( &bound_type, - *par.nullable, - par.instance_parameter, + par.nullable, + par.is_instance_parameter, par.move_, )); if r#async && (par.name == "callback" || par.name.ends_with("_callback")) { - let func_name = func.c_identifier.as_ref().unwrap(); + let func_name = &func.c_identifier; let finish_func_name = if let Some(finish_func_name) = &func.finish_func { finish_func_name.to_string() } else { @@ -120,19 +120,19 @@ impl Bounds { find_out_parameters(env, function, configured_functions); if use_function_return_for_result( env, - function.ret.typ, + function.ret.typ(), &func.name, configured_functions, ) { let nullable = configured_functions .iter() .find_map(|f| f.ret.nullable) - .unwrap_or(function.ret.nullable); + .unwrap_or(function.ret.is_nullable()); out_parameters.insert( 0, - RustType::builder(env, function.ret.typ) - .direction(function.ret.direction) + RustType::builder(env, function.ret.typ()) + .direction(function.ret.direction()) .nullable(nullable) .try_build() .into_string(), @@ -187,16 +187,16 @@ impl Bounds { }); } } - if (!need_is_into_check || !*par.nullable) && par.c_type != "GDestroyNotify" { + if (!need_is_into_check || !par.nullable) && par.c_type != "GDestroyNotify" { self.add_parameter(&par.name, &type_string, bound_type, r#async); } } - } else if par.instance_parameter + } else if par.is_instance_parameter && let Some(bound_type) = Bounds::type_for(env, par.typ) { ret = Some(Bounds::get_to_glib_extra( &bound_type, - *par.nullable, + par.nullable, true, par.move_, )); @@ -229,7 +229,7 @@ impl Bounds { pub fn get_to_glib_extra( bound_type: &BoundType, nullable: bool, - instance_parameter: bool, + is_instance_parameter: bool, move_: bool, ) -> String { use self::BoundType::*; @@ -239,7 +239,7 @@ impl Bounds { AsRef(_) if move_ => ".upcast()".to_owned(), AsRef(_) => ".as_ref()".to_owned(), IsA(_) if move_ && nullable => ".map(|p| p.upcast())".to_owned(), - IsA(_) if nullable && !instance_parameter => ".map(|p| p.as_ref())".to_owned(), + IsA(_) if nullable && !is_instance_parameter => ".map(|p| p.as_ref())".to_owned(), IsA(_) if move_ => ".upcast()".to_owned(), IsA(_) => ".as_ref()".to_owned(), _ => String::new(), @@ -333,9 +333,7 @@ fn find_out_parameters( .iter() .enumerate() .filter(|&(index, param)| { - Some(index) != index_to_ignore - && param.direction == ParameterDirection::Out - && param.name != "error" + Some(index) != index_to_ignore && param.direction().is_out() && !param.is_error() }) .map(|(_, param)| { // FIXME: This should work completely based on the analysis of the finish() @@ -346,13 +344,13 @@ fn find_out_parameters( .find_map(|f| { f.parameters .iter() - .filter(|p| p.ident.is_match(¶m.name)) + .filter(|p| p.ident.is_match(param.name())) .find_map(|p| p.nullable) }) - .unwrap_or(param.nullable); + .unwrap_or(param.is_nullable()); - RustType::builder(env, param.typ) - .direction(param.direction) + RustType::builder(env, param.typ()) + .direction(param.direction()) .nullable(nullable) .try_build() .into_string() @@ -372,11 +370,11 @@ fn find_error_type(env: &Env, function: &Function) -> Option { let error_param = function .parameters .iter() - .find(|param| param.direction.is_out() && param.is_error)?; - if let Type::Record(_) = env.type_(error_param.typ) { + .find(|param| param.direction().is_out() && param.is_error())?; + if let Type::Record(_) = env.type_(error_param.typ()) { Some( - RustType::builder(env, error_param.typ) - .direction(error_param.direction) + RustType::builder(env, error_param.typ()) + .direction(error_param.direction()) .try_build() .into_string(), ) diff --git a/src/analysis/child_properties.rs b/src/analysis/child_properties.rs index 98bf3280e..d4f16597d 100644 --- a/src/analysis/child_properties.rs +++ b/src/analysis/child_properties.rs @@ -23,7 +23,7 @@ pub struct ChildProperty { pub typ: library::TypeId, pub child_name: String, pub child_type: Option, - pub nullable: library::Nullable, + pub nullable: bool, pub get_out_ref_mode: RefMode, pub set_in_ref_mode: RefMode, pub doc_hidden: bool, @@ -117,7 +117,7 @@ fn analyze_property( if set_in_ref_mode == RefMode::ByRefMut { set_in_ref_mode = RefMode::ByRef; } - let nullable = library::Nullable(set_in_ref_mode.is_ref()); + let nullable = set_in_ref_mode.is_ref(); let mut bounds_str = String::new(); let dir = ParameterDirection::In; diff --git a/src/analysis/enums.rs b/src/analysis/enums.rs index a66a8038e..aac298925 100644 --- a/src/analysis/enums.rs +++ b/src/analysis/enums.rs @@ -77,7 +77,7 @@ pub fn new(env: &Env, obj: &GObject, imports: &mut Imports) -> Option { let first_param = &mut f.parameters.c_parameters[0]; if first_param.typ == enumeration_tid { - first_param.instance_parameter = true; + first_param.is_instance_parameter = true; let t = f .parameters diff --git a/src/analysis/flags.rs b/src/analysis/flags.rs index 0aeae4d97..92ba5a3a6 100644 --- a/src/analysis/flags.rs +++ b/src/analysis/flags.rs @@ -73,7 +73,7 @@ pub fn new(env: &Env, obj: &GObject, imports: &mut Imports) -> Option { let first_param = &mut f.parameters.c_parameters[0]; if first_param.typ == flags_tid { - first_param.instance_parameter = true; + first_param.is_instance_parameter = true; let t = f .parameters diff --git a/src/analysis/function_parameters.rs b/src/analysis/function_parameters.rs index 88fcc1397..a9a9c678f 100644 --- a/src/analysis/function_parameters.rs +++ b/src/analysis/function_parameters.rs @@ -9,7 +9,7 @@ use crate::{ analysis::{self, bounds::Bounds}, config::{self, parameter_matchable::ParameterMatchable}, env::Env, - library::{self, Nullable, ParameterScope, Transfer, TypeId}, + library::{self, TypeId}, nameutil, traits::IntoString, }; @@ -23,23 +23,25 @@ pub struct Parameter { impl Parameter { pub fn from_parameter( env: &Env, - lib_par: &library::Parameter, + lib_par: library::Parameter, configured_parameters: &[&config::functions::Parameter], ) -> Self { + let ty = lib_par.typ(); Parameter { - lib_par: lib_par.clone(), - try_from_glib: TryFromGlib::from_parameter(env, lib_par.typ, configured_parameters), + lib_par, + try_from_glib: TryFromGlib::from_parameter(env, ty, configured_parameters), } } pub fn from_return_value( env: &Env, - lib_par: &library::Parameter, + lib_par: library::Parameter, configured_functions: &[&config::functions::Function], ) -> Self { + let ty = lib_par.typ(); Parameter { - lib_par: lib_par.clone(), - try_from_glib: TryFromGlib::from_return_value(env, lib_par.typ, configured_functions), + lib_par, + try_from_glib: TryFromGlib::from_return_value(env, ty, configured_functions), } } } @@ -57,13 +59,13 @@ pub struct CParameter { pub name: String, pub typ: TypeId, pub c_type: String, - pub instance_parameter: bool, + pub is_instance_parameter: bool, pub direction: library::ParameterDirection, - pub nullable: library::Nullable, - pub transfer: library::Transfer, + pub nullable: bool, + pub transfer: gir_parser::TransferOwnership, pub caller_allocates: bool, pub is_error: bool, - pub scope: ParameterScope, + pub scope: Option, /// Index of the user data parameter associated with the callback. pub user_data_index: Option, /// Index of the destroy notification parameter associated with the @@ -83,13 +85,13 @@ pub enum TransformationType { }, ToGlibScalar { name: String, - nullable: library::Nullable, + nullable: bool, needs_into: bool, }, ToGlibPointer { name: String, - instance_parameter: bool, - transfer: library::Transfer, + is_instance_parameter: bool, + transfer: gir_parser::TransferOwnership, ref_mode: RefMode, // filled by functions to_glib_extra: String, @@ -159,7 +161,7 @@ impl Parameters { pub fn analyze_return(&mut self, env: &Env, ret: &Option) { let ret_data = ret .as_ref() - .map(|r| (r.lib_par.array_length, &r.try_from_glib)); + .map(|r| (r.lib_par.array_length(), &r.try_from_glib)); let (ind_c, try_from_glib) = match ret_data { Some((Some(array_length), try_from_glib)) => (array_length as usize, try_from_glib), @@ -195,43 +197,44 @@ pub fn analyze( // Map: length argument position => parameter let array_lengths: HashMap = function_parameters .iter() - .filter_map(|p| p.array_length.map(|pos| (pos, p))) + .filter_map(|p| p.array_length().map(|pos| (pos, p))) .collect(); let mut to_remove = Vec::new(); let mut correction_instance = 0; for par in function_parameters.iter() { - if par.scope.is_none() { + if par.scope().is_none() { continue; } - if let Some(index) = par.closure { + if let Some(index) = par.closure() { to_remove.push(index); } - if let Some(index) = par.destroy { + if let Some(index) = par.destroy() { to_remove.push(index); } } for (pos, par) in function_parameters.iter().enumerate() { - let name = if par.instance_parameter { - par.name.clone() + let is_instance_parameter = par.is_instance(); + let name = if is_instance_parameter { + par.name().to_owned() } else { - nameutil::mangle_keywords(&*par.name).into_owned() + nameutil::mangle_keywords(par.name()).into_owned() }; - if par.instance_parameter { + if is_instance_parameter { correction_instance = 1; } let configured_parameters = configured_functions.matched_parameters(&name); - let c_type = par.c_type.clone(); - let typ = override_string_type_parameter(env, par.typ, &configured_parameters); + let c_type = par.c_type(); + let typ = override_string_type_parameter(env, par.typ(), &configured_parameters); let ind_c = parameters.c_parameters.len(); let mut ind_rust = Some(parameters.rust_parameters.len()); - let mut add_rust_parameter = match par.direction { + let mut add_rust_parameter = match par.direction() { library::ParameterDirection::In | library::ParameterDirection::InOut => true, library::ParameterDirection::Return => false, library::ParameterDirection::Out => !can_as_return(env, par) && !async_func, @@ -246,9 +249,9 @@ pub fn analyze( { add_rust_parameter = false; } - let mut transfer = par.transfer; + let mut transfer = par.transfer_ownership(); - let mut caller_allocates = par.caller_allocates; + let mut caller_allocates = par.is_caller_allocates(); let conversion = ConversionType::of(env, typ); if let ConversionType::Direct | ConversionType::Scalar @@ -257,7 +260,7 @@ pub fn analyze( { // For simple types no reason to have these flags caller_allocates = false; - transfer = library::Transfer::None; + transfer = gir_parser::TransferOwnership::None; } let move_ = configured_parameters .iter() @@ -269,13 +272,13 @@ pub fn analyze( if matches!(env.library.type_(typ), library::Type::CArray(_)) { false } else { - transfer == Transfer::Full && par.direction.is_in() + transfer == gir_parser::TransferOwnership::Full && par.direction().is_in() } }); let mut array_par = configured_parameters.iter().find_map(|cp| { cp.length_of .as_ref() - .and_then(|n| function_parameters.iter().find(|fp| fp.name == *n)) + .and_then(|n| function_parameters.iter().find(|fp| fp.name() == *n)) }); if array_par.is_none() { array_par = array_lengths.get(&(pos as u32)).copied(); @@ -284,13 +287,13 @@ pub fn analyze( array_par = detect_length(env, pos, par, function_parameters); } if let Some(array_par) = array_par { - let mut array_name = nameutil::mangle_keywords(&array_par.name); - if let Some(bound_type) = Bounds::type_for(env, array_par.typ) { + let mut array_name = nameutil::mangle_keywords(array_par.name()); + if let Some(bound_type) = Bounds::type_for(env, array_par.typ()) { array_name = (array_name.into_owned() + &Bounds::get_to_glib_extra( &bound_type, - *array_par.nullable, - array_par.instance_parameter, + array_par.is_nullable(), + array_par.is_instance(), move_, )) .into(); @@ -301,34 +304,34 @@ pub fn analyze( let transformation = Transformation { ind_c, ind_rust: None, - transformation_type: get_length_type(env, &array_name, &par.name, typ), + transformation_type: get_length_type(env, &array_name, par.name(), typ), }; parameters.transformations.push(transformation); } let immutable = configured_parameters.iter().any(|p| p.constant); let ref_mode = - RefMode::without_unneeded_mut(env, par, immutable, in_trait && par.instance_parameter); + RefMode::without_unneeded_mut(env, par, immutable, in_trait && is_instance_parameter); let nullable_override = configured_parameters.iter().find_map(|p| p.nullable); - let nullable = nullable_override.unwrap_or(par.nullable); + let nullable = nullable_override.unwrap_or(par.is_nullable()); let try_from_glib = TryFromGlib::from_parameter(env, typ, &configured_parameters); let c_par = CParameter { name: name.clone(), typ, - c_type, - instance_parameter: par.instance_parameter, - direction: par.direction, + c_type: c_type.to_owned(), + is_instance_parameter, + direction: par.direction(), transfer, caller_allocates, nullable, ref_mode, - is_error: par.is_error, - scope: par.scope, - user_data_index: par.closure, - destroy_index: par.destroy, + is_error: matches!(par, library::Parameter::Error(_)), + scope: par.scope(), + user_data_index: par.closure(), + destroy_index: par.destroy(), try_from_glib: try_from_glib.clone(), move_, }; @@ -350,7 +353,7 @@ pub fn analyze( let transformation_type = match conversion { ConversionType::Direct => { - if par.c_type != "GLib.Pid" { + if par.c_type() != "GLib.Pid" { TransformationType::ToGlibDirect { name } } else { TransformationType::ToGlibScalar { @@ -367,48 +370,50 @@ pub fn analyze( }, ConversionType::Option => { let needs_into = match try_from_glib { - TryFromGlib::Option => par.direction == library::ParameterDirection::In, + TryFromGlib::Option => par.direction().is_in(), TryFromGlib::OptionMandatory => false, other => unreachable!("{:?} inconsistent / conversion type", other), }; TransformationType::ToGlibScalar { name, - nullable: Nullable(false), + nullable: false, needs_into, } } ConversionType::Result { .. } => { let needs_into = match try_from_glib { - TryFromGlib::Result { .. } => par.direction == library::ParameterDirection::In, + TryFromGlib::Result { .. } => par.direction().is_in(), TryFromGlib::ResultInfallible { .. } => false, other => unreachable!("{:?} inconsistent / conversion type", other), }; TransformationType::ToGlibScalar { name, - nullable: Nullable(false), + nullable: false, needs_into, } } ConversionType::Pointer => TransformationType::ToGlibPointer { name, - instance_parameter: par.instance_parameter, + is_instance_parameter, transfer, ref_mode, to_glib_extra: Default::default(), explicit_target_type: Default::default(), pointer_cast: if matches!(env.library.type_(typ), library::Type::CArray(_)) - && par.c_type == "gpointer" + && par.c_type() == "gpointer" { format!(" as {}", nameutil::use_glib_if_needed(env, "ffi::gpointer")) } else { Default::default() }, in_trait, - nullable: *nullable, + nullable, move_, }, ConversionType::Borrow => TransformationType::ToGlibBorrow, - ConversionType::Unknown => TransformationType::ToGlibUnknown { name }, + ConversionType::Unknown => TransformationType::ToGlibUnknown { + name: name.to_owned(), + }, }; let mut transformation = Transformation { @@ -468,7 +473,7 @@ fn detect_length<'a>( } parameters.get(pos - 1).and_then(|p| { - if has_length(env, p.typ) { + if has_length(env, p.typ()) { Some(p) } else { None @@ -477,16 +482,16 @@ fn detect_length<'a>( } fn is_length(par: &library::Parameter) -> bool { - if par.direction != library::ParameterDirection::In { + if !par.direction().is_in() { return false; } - let len = par.name.len(); - if len >= 3 && &par.name[len - 3..len] == "len" { + let len = par.name().len(); + if len >= 3 && &par.name()[len - 3..len] == "len" { return true; } - par.name.contains("length") + par.name().contains("length") } fn has_length(env: &Env, typ: TypeId) -> bool { diff --git a/src/analysis/functions.rs b/src/analysis/functions.rs index fa542310d..b79227e92 100644 --- a/src/analysis/functions.rs +++ b/src/analysis/functions.rs @@ -29,10 +29,7 @@ use crate::{ codegen::Visibility, config::{self, gobjects::GStatus}, env::Env, - library::{ - self, Function, FunctionKind, MAIN_NAMESPACE, ParameterDirection, ParameterScope, Transfer, - Type, - }, + library::{self, Function, FunctionKind, MAIN_NAMESPACE, ParameterDirection, Type}, nameutil, traits::*, version::Version, @@ -242,23 +239,23 @@ fn fixup_gpointer_parameter( ) { use crate::analysis::ffi_type; - let instance_parameter = idx == 0; + let is_instance_parameter = idx == 0; let glib_name = env.library.type_(type_tid).get_glib_name().unwrap(); let ffi_name = ffi_type::ffi_type(env, type_tid, glib_name).unwrap(); let pointer_type = if is_boxed { "*const" } else { "*mut" }; parameters.rust_parameters[idx].typ = type_tid; parameters.c_parameters[idx].typ = type_tid; - parameters.c_parameters[idx].instance_parameter = instance_parameter; + parameters.c_parameters[idx].is_instance_parameter = is_instance_parameter; parameters.c_parameters[idx].ref_mode = RefMode::ByRef; - parameters.c_parameters[idx].transfer = Transfer::None; + parameters.c_parameters[idx].transfer = gir_parser::TransferOwnership::None; parameters.transformations[idx] = Transformation { ind_c: idx, ind_rust: Some(idx), transformation_type: TransformationType::ToGlibPointer { name: parameters.rust_parameters[idx].name.clone(), - instance_parameter, - transfer: Transfer::None, + is_instance_parameter, + transfer: gir_parser::TransferOwnership::None, ref_mode: RefMode::ByRef, to_glib_extra: Default::default(), explicit_target_type: format!("{} {}", pointer_type, ffi_name.as_str()), @@ -343,16 +340,13 @@ fn analyze_callbacks( // account the actual closure parameter. let mut c_parameters = Vec::new(); for (pos, par) in parameters.c_parameters.iter().enumerate() { - if par.instance_parameter { + if par.is_instance_parameter { continue; } c_parameters.push((par, pos)); } - let func_name = match &func.c_identifier { - Some(n) => n, - None => &func.name, - }; + let func_name = &func.c_identifier; let mut destructors_to_update = Vec::new(); for pos in 0..parameters.c_parameters.len() { // If it is a user data parameter, we ignore it. @@ -362,9 +356,9 @@ fn analyze_callbacks( } let par = ¶meters.c_parameters[pos]; assert!( - !par.instance_parameter || pos == 0, + !par.is_instance_parameter || pos == 0, "Wrong instance parameter in {}", - func.c_identifier.as_ref().unwrap() + func.c_identifier ); if let Ok(rust_type) = RustType::builder(env, par.typ) .direction(par.direction) @@ -374,7 +368,7 @@ fn analyze_callbacks( used_types.extend(rust_type.into_used_types()); } let rust_type = env.library.type_(par.typ); - let callback_info = if !*par.nullable || !rust_type.is_function() { + let callback_info = if !par.nullable || !rust_type.is_function() { let (to_glib_extra, callback_info) = bounds.add_for_parameter( env, func, @@ -514,8 +508,8 @@ fn analyze_callbacks( if !destroys.is_empty() || !callbacks.is_empty() { for (pos, typ) in to_replace { let ty = env.library.type_(typ); - params[pos].typ = typ; - params[pos].c_type = ty.get_glib_name().unwrap().to_owned(); + params[pos].set_tid(typ); + params[pos].set_c_type(ty.get_glib_name().unwrap()); } let mut s = to_remove .iter() @@ -563,13 +557,16 @@ fn analyze_function( let type_tid = type_tid.unwrap_or_default(); let r#async = func.finish_func.is_some() || func.parameters.iter().any(|parameter| { - parameter.scope == ParameterScope::Async && parameter.c_type == "GAsyncReadyCallback" + parameter + .scope() + .is_some_and(|s| s == gir_parser::FunctionScope::Async) + && parameter.c_type() == "GAsyncReadyCallback" }); let has_callback_parameter = !r#async && func .parameters .iter() - .any(|par| env.library.type_(par.typ).is_function()); + .any(|par| env.library.type_(par.typ()).is_function()); let concurrency = match env.library.type_(type_tid) { library::Type::Class(_) | library::Type::Interface(_) | library::Type::Record(_) => { obj.concurrency @@ -591,7 +588,7 @@ fn analyze_function( && func .parameters .iter() - .any(|par| par.c_type == "GDestroyNotify") + .any(|par| par.c_type() == "GDestroyNotify") { // In here, We have a DestroyNotify callback but no other callback is provided. // A good example of this situation is this function: @@ -629,11 +626,11 @@ fn analyze_function( let nb_in_params = func .parameters .iter() - .filter(|param| library::ParameterDirection::In == param.direction) + .filter(|param| param.direction().is_in()) .fold(0, |acc, _| acc + 1); let is_bool_getter = (func.parameters.len() == nb_in_params) - && (func.ret.typ == library::TypeId::tid_bool() - || func.ret.typ == library::TypeId::tid_c_bool()); + && (func.ret.typ() == library::TypeId::tid_bool() + || func.ret.typ() == library::TypeId::tid_c_bool()); new_name = getter_rules::try_rename_would_be_getter(&name, is_bool_getter) .ok() .map(getter_rules::NewName::unwrap); @@ -697,7 +694,7 @@ fn analyze_function( parameters.analyze_return(env, &ret.parameter); if let Some(ref f) = ret.parameter - && let Type::Function(_) = env.library.type_(f.lib_par.typ) + && let Type::Function(_) = env.library.type_(f.lib_par.typ()) && env.config.work_mode.is_normal() { warn!("Function \"{}\" returns callback", func.name); @@ -734,7 +731,7 @@ fn analyze_function( } } for (pos, par) in parameters.c_parameters.iter().enumerate() { - if par.instance_parameter { + if par.is_instance_parameter { correction_instance = 1; } @@ -745,9 +742,9 @@ fn analyze_function( continue; } assert!( - !par.instance_parameter || pos == 0, + !par.is_instance_parameter || pos == 0, "Wrong instance parameter in {}", - func.c_identifier.as_ref().unwrap() + func.c_identifier ); if let Ok(rust_type) = RustType::builder(env, par.typ) .direction(par.direction) @@ -848,7 +845,7 @@ fn analyze_function( warn_main!( type_tid, "Function {} has unsupported outs", - func.c_identifier.as_ref().unwrap_or(&func.name) + func.c_identifier ); commented = true; } @@ -859,7 +856,7 @@ fn analyze_function( if let Some(ref trampoline) = trampoline { for out in &trampoline.output_params { - if let Ok(rust_type) = RustType::builder(env, out.lib_par.typ) + if let Ok(rust_type) = RustType::builder(env, out.lib_par.typ()) .direction(ParameterDirection::Out) .try_build() { @@ -867,7 +864,7 @@ fn analyze_function( } } if let Some(ref out) = trampoline.ffi_ret - && let Ok(rust_type) = RustType::builder(env, out.lib_par.typ) + && let Ok(rust_type) = RustType::builder(env, out.lib_par.typ()) .direction(ParameterDirection::Return) .try_build() { @@ -878,7 +875,9 @@ fn analyze_function( if status.need_generate() && !commented { if (!destroys.is_empty() || !callbacks.is_empty()) - && callbacks.iter().any(|c| !c.scope.is_call()) + && callbacks + .iter() + .any(|c| !c.scope.is_some_and(|s| s.is_call())) { imports.add("std::boxed::Box as Box_"); } @@ -916,7 +915,7 @@ fn analyze_function( name, func_name: func_name.to_string(), new_name, - glib_name: func.c_identifier.as_ref().unwrap().clone(), + glib_name: func.c_identifier.clone(), status, kind: func.kind, visibility, @@ -982,7 +981,7 @@ fn analyze_async( { // Checks for /*Ignored*/ or other error comments *commented |= callback_type.contains("/*"); - let func_name = func.c_identifier.as_ref().unwrap(); + let func_name = &func.c_identifier; let finish_func_name = if let Some(finish_func_name) = &func.finish_func { finish_func_name.to_string() } else { @@ -993,26 +992,26 @@ fn analyze_async( if let Some(function) = find_function(env, &finish_func_name) { if use_function_return_for_result( env, - function.ret.typ, + function.ret.typ(), &func.name, configured_functions, ) { ffi_ret = Some(analysis::Parameter::from_return_value( env, - &function.ret, + function.ret.clone(), configured_functions, )); } for param in &function.parameters { let mut lib_par = param.clone(); - if nameutil::needs_mangling(¶m.name) { - lib_par.name = nameutil::mangle_keywords(&*param.name).into_owned(); + if nameutil::needs_mangling(param.name()) { + lib_par.set_name(&nameutil::mangle_keywords(param.name())); } - let configured_parameters = configured_functions.matched_parameters(&lib_par.name); + let configured_parameters = configured_functions.matched_parameters(lib_par.name()); output_params.push(analysis::Parameter::from_parameter( env, - &lib_par, + lib_par, &configured_parameters, )); } @@ -1145,7 +1144,8 @@ fn analyze_callback( // If we don't have a "user data" parameter, we can't get the closure so there's // nothing we can do... if par.c_type != "GDestroyNotify" - && (func.parameters.is_empty() || !func.parameters.iter().any(|c| c.closure.is_some())) + && (func.parameters.is_empty() + || !func.parameters.iter().any(|c| c.closure().is_some())) { *commented = true; warn_main!( @@ -1166,7 +1166,7 @@ fn analyze_callback( ); if par.c_type != "GDestroyNotify" && !*commented { *commented |= func.parameters.iter().any(|p| { - if p.closure.is_none() { + if p.closure().is_none() { crate::analysis::trampolines::type_error(env, p).is_some() } else { false @@ -1183,7 +1183,7 @@ fn analyze_callback( imports_to_add.extend(rust_type.into_used_types()); } } - if let Ok(rust_type) = RustType::builder(env, func.ret.typ) + if let Ok(rust_type) = RustType::builder(env, func.ret.typ()) .direction(ParameterDirection::Return) .try_build() && !rust_type.as_str().ends_with("GString") @@ -1266,17 +1266,12 @@ fn analyze_callback( pub fn find_function<'a>(env: &'a Env, c_identifier: &str) -> Option<&'a Function> { let find = |functions: &'a [Function]| -> Option<&'a Function> { - for function in functions { - if let Some(ref func_c_identifier) = function.c_identifier - && func_c_identifier == c_identifier - { - return Some(function); - } - } - None + functions + .iter() + .find(|&function| function.c_identifier == c_identifier) }; - if let Some(index) = env.library.find_namespace(&env.config.library_name) { + if let Some((index, _)) = env.library.find_namespace(&env.config.library_name) { let namespace = env.library.namespace(index); if let Some(f) = find(&namespace.functions) { return Some(f); @@ -1312,8 +1307,8 @@ pub fn find_index_to_ignore<'a>( parameters .into_iter() .chain(ret) - .find(|param| param.array_length.is_some()) - .and_then(|param| param.array_length.map(|length| length as usize)) + .find(|param| param.array_length().is_some()) + .and_then(|param| param.array_length().map(|length| length as usize)) } #[cfg(test)] diff --git a/src/analysis/out_parameters.rs b/src/analysis/out_parameters.rs index f23669d2f..56558e8da 100644 --- a/src/analysis/out_parameters.rs +++ b/src/analysis/out_parameters.rs @@ -9,9 +9,7 @@ use crate::{ }, config::{self, parameter_matchable::ParameterMatchable}, env::Env, - library::{ - self, Basic, Function, INTERNAL_NAMESPACE, Nullable, ParameterDirection, Type, TypeId, - }, + library::{self, Basic, Function, INTERNAL_NAMESPACE, ParameterDirection, Type, TypeId}, nameutil, }; @@ -64,10 +62,10 @@ pub fn analyze( let return_strategy = decide_throw_function_return_strategy(env, func_ret, &func.name, configured_functions); info.mode = Mode::Throws(return_strategy); - } else if func.ret.typ == TypeId::tid_none() { + } else if func.ret.typ() == TypeId::tid_none() { info.mode = Mode::Normal; - } else if func.ret.typ == TypeId::tid_bool() || func.ret.typ == TypeId::tid_c_bool() { - if nullable_override == Some(Nullable(false)) { + } else if func.ret.typ() == TypeId::tid_bool() || func.ret.typ() == TypeId::tid_c_bool() { + if nullable_override == Some(false) { info.mode = Mode::Combined; } else { info.mode = Mode::Optional; @@ -77,25 +75,25 @@ pub fn analyze( } for lib_par in &func.parameters { - if lib_par.direction != ParameterDirection::Out { + if !lib_par.direction().is_out() { continue; } if can_as_return(env, lib_par) { + let new_name = nameutil::mangle_keywords(lib_par.name()); let mut lib_par = lib_par.clone(); - lib_par.name = nameutil::mangle_keywords(&lib_par.name).into_owned(); - let configured_parameters = configured_functions.matched_parameters(&lib_par.name); - let mut out = - analysis::Parameter::from_parameter(env, &lib_par, &configured_parameters); + lib_par.set_name(&new_name); + let configured_parameters = configured_functions.matched_parameters(lib_par.name()); + let mut out = analysis::Parameter::from_parameter(env, lib_par, &configured_parameters); // FIXME: temporary solution for string_type, nullable override. This should // completely work based on the analyzed parameters instead of the // library parameters. if let Some(c_par) = func_c_params .iter() - .find(|c_par| c_par.name == lib_par.name) + .find(|c_par| c_par.name == out.lib_par.name()) { - out.lib_par.typ = c_par.typ; - out.lib_par.nullable = c_par.nullable; + out.lib_par.set_tid(c_par.typ); + out.lib_par.set_nullable(c_par.nullable); } info.params.push(out); @@ -110,14 +108,15 @@ pub fn analyze( if info.mode == Mode::Combined || info.mode == Mode::Throws(ThrowFunctionReturnStrategy::ReturnResult) { - let mut ret = analysis::Parameter::from_return_value(env, &func.ret, configured_functions); + let mut ret = + analysis::Parameter::from_return_value(env, func.ret.clone(), configured_functions); // TODO: fully switch to use analyzed returns (it add too many Return>) if let Some(ref par) = func_ret.parameter { - ret.lib_par.typ = par.lib_par.typ; + ret.lib_par.set_tid(par.lib_par.typ()); } if let Some(val) = nullable_override { - ret.lib_par.nullable = val; + ret.lib_par.set_nullable(val); } info.params.insert(0, ret); } @@ -127,17 +126,17 @@ pub fn analyze( pub fn can_as_return(env: &Env, par: &library::Parameter) -> bool { use super::conversion_type::ConversionType::*; - match ConversionType::of(env, par.typ) { + match ConversionType::of(env, par.typ()) { Direct | Scalar | Option | Result { .. } => true, Pointer => { // Disallow Basic arrays without length - if is_carray_with_direct_elements(env, par.typ) && par.array_length.is_none() { + if is_carray_with_direct_elements(env, par.typ()) && par.array_length().is_none() { return false; } - RustType::builder(env, par.typ) + RustType::builder(env, par.typ()) .direction(ParameterDirection::Out) - .scope(par.scope) + .scope(par.scope()) .try_build_param() .is_ok() } @@ -155,7 +154,7 @@ fn decide_throw_function_return_strategy( let typ = ret .parameter .as_ref() - .map(|par| par.lib_par.typ) + .map(|par| par.lib_par.typ()) .unwrap_or_default(); if env.type_(typ).eq(&Type::Basic(Basic::None)) { ThrowFunctionReturnStrategy::Void diff --git a/src/analysis/properties.rs b/src/analysis/properties.rs index 4e3c1eef6..d0417baac 100644 --- a/src/analysis/properties.rs +++ b/src/analysis/properties.rs @@ -25,7 +25,7 @@ pub struct Property { pub is_get: bool, pub func_name: String, pub func_name_alias: Option, - pub nullable: library::Nullable, + pub nullable: bool, pub get_out_ref_mode: RefMode, pub set_in_ref_mode: RefMode, pub bounds: Bounds, @@ -291,7 +291,7 @@ fn analyze_property( let set_bound = PropertyBound::get(env, prop.typ); if type_string.is_ok() && set_bound.is_some() { imports.add("glib::prelude::*"); - if !*nullable { + if !nullable { // TODO: support non-nullable setter if found any warn!( "Non nullable setter for property generated as nullable \"{type_name}.{name}\"" @@ -336,30 +336,16 @@ fn analyze_property( let notify_signal = if notifiable { let mut used_types: Vec = Vec::with_capacity(4); + let tid = env + .library + .find_type(library::INTERNAL_NAMESPACE, "none") + .unwrap(); let trampoline = trampolines::analyze( env, &library::Signal { name: format!("notify::{name}"), parameters: Vec::new(), - ret: library::Parameter { - name: String::new(), - typ: env - .library - .find_type(library::INTERNAL_NAMESPACE, "none") - .unwrap(), - c_type: "none".into(), - instance_parameter: false, - direction: library::ParameterDirection::Return, - transfer: library::Transfer::None, - caller_allocates: false, - nullable: library::Nullable(false), - array_length: None, - is_error: false, - doc: None, - scope: library::ParameterScope::None, - closure: None, - destroy: None, - }, + ret: library::Parameter::none(tid), is_action: false, is_detailed: false, /* well, technically this *is* an instance of a detailed * signal, but we "pre-detailed" it */ @@ -442,15 +428,12 @@ fn get_func_name(prop_name: &str, is_bool_getter: bool) -> (Vec, String) } } -pub fn get_property_ref_modes( - env: &Env, - prop: &library::Property, -) -> (RefMode, RefMode, library::Nullable) { +pub fn get_property_ref_modes(env: &Env, prop: &library::Property) -> (RefMode, RefMode, bool) { let get_out_ref_mode = RefMode::of(env, prop.typ, library::ParameterDirection::Return); let mut set_in_ref_mode = RefMode::of(env, prop.typ, library::ParameterDirection::In); if set_in_ref_mode == RefMode::ByRefMut { set_in_ref_mode = RefMode::ByRef; } - let nullable = library::Nullable(set_in_ref_mode.is_ref()); + let nullable = set_in_ref_mode.is_ref(); (get_out_ref_mode, set_in_ref_mode, nullable) } diff --git a/src/analysis/ref_mode.rs b/src/analysis/ref_mode.rs index 4b87f5c07..a350aecb1 100644 --- a/src/analysis/ref_mode.rs +++ b/src/analysis/ref_mode.rs @@ -94,11 +94,11 @@ impl RefMode { immutable: bool, self_in_trait: bool, ) -> Self { - let ref_mode = Self::of(env, par.typ, par.direction); + let ref_mode = Self::of(env, par.typ(), par.direction()); match ref_mode { - Self::ByRefMut if !is_mut_ptr(&par.c_type) => Self::ByRef, + Self::ByRefMut if !is_mut_ptr(par.c_type()) => Self::ByRef, Self::ByRefMut if immutable => Self::ByRefImmut, - Self::ByRef if self_in_trait && !is_mut_ptr(&par.c_type) => Self::ByRefConst, + Self::ByRef if self_in_trait && !is_mut_ptr(par.c_type()) => Self::ByRefConst, ref_mode => ref_mode, } } diff --git a/src/analysis/return_value.rs b/src/analysis/return_value.rs index 96c02a32d..a95045d22 100644 --- a/src/analysis/return_value.rs +++ b/src/analysis/return_value.rs @@ -7,7 +7,7 @@ use crate::{ }, config, env::Env, - library::{self, Nullable, TypeId}, + library::{self, TypeId}, }; #[derive(Clone, Debug, Default)] @@ -32,30 +32,30 @@ pub fn analyze( .iter() .find_map(|f| f.ret.type_name.as_ref()) .and_then(|typ| env.library.find_type(0, typ)) - .unwrap_or_else(|| override_string_type_return(env, func.ret.typ, configured_functions)); + .unwrap_or_else(|| override_string_type_return(env, func.ret.typ(), configured_functions)); let mut parameter = if typ == Default::default() { None } else { - let mut nullable = func.ret.nullable; + let mut is_nullable = func.ret.is_nullable(); if !obj.trust_return_value_nullability { // Since GIRs are bad at specifying return value nullability, assume // any returned pointer is nullable unless overridden by the config. - if !*nullable && can_be_nullable_return(env, typ) { - *nullable = true; + if !is_nullable && can_be_nullable_return(env, typ) { + is_nullable = true; } } let nullable_override = configured_functions.iter().find_map(|f| f.ret.nullable); if let Some(val) = nullable_override { - nullable = val; + is_nullable = val; } - Some(library::Parameter { - typ, - nullable, - ..func.ret.clone() - }) + let mut ret = func.ret.clone(); + ret.set_tid(typ); + ret.set_nullable(is_nullable); + Some(ret) }; + let param_is_nullable = parameter.as_ref().is_some_and(|p| p.is_nullable()); let mut commented = false; let bool_return_is_error = configured_functions @@ -84,7 +84,7 @@ pub fn analyze( .iter() .find_map(|f| f.ret.nullable_return_is_error.as_ref()); let nullable_return_error_message = nullable_return_is_error.and_then(|m| { - if let Some(library::Parameter { nullable: Nullable(false), ..}) = parameter { + if !param_is_nullable{ error!( "Ignoring nullable_return_is_error configuration for non-none returning function {}", func.name @@ -105,23 +105,21 @@ pub fn analyze( let mut base_tid = None; if func.kind == library::FunctionKind::Constructor - && let Some(par) = parameter + && let Some(ref mut par) = parameter { let nullable_override = configured_functions.iter().find_map(|f| f.ret.nullable); - if par.typ != type_tid { - base_tid = Some(par.typ); + if par.typ() != type_tid { + base_tid = Some(par.typ()); } - parameter = Some(library::Parameter { - typ: type_tid, - nullable: nullable_override.unwrap_or(func.ret.nullable), - ..par - }); + par.set_nullable(nullable_override.unwrap_or(func.ret.is_nullable())); + par.set_tid(type_tid); } - let parameter = parameter.as_ref().map(|lib_par| { - let par = analysis::Parameter::from_return_value(env, lib_par, configured_functions); + let parameter = parameter.map(|lib_par| { + let par = + analysis::Parameter::from_return_value(env, lib_par.clone(), configured_functions); if let Ok(rust_type) = RustType::builder(env, typ) - .direction(par.lib_par.direction) + .direction(par.lib_par.direction()) .try_from_glib(&par.try_from_glib) .try_build() { @@ -129,7 +127,7 @@ pub fn analyze( } commented = RustType::builder(env, typ) - .direction(func.ret.direction) + .direction(func.ret.direction()) .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 a7590dd37..3c136c4ff 100644 --- a/src/analysis/rust_type.rs +++ b/src/analysis/rust_type.rs @@ -5,7 +5,7 @@ use crate::{ analysis::{record_type::RecordType, ref_mode::RefMode, try_from_glib::TryFromGlib}, config::functions::{CallbackParameter, CallbackParameters}, env::Env, - library::{self, Nullable, ParameterDirection, ParameterScope}, + library::{self, ParameterDirection}, nameutil::{is_gstring, use_glib_type}, traits::*, }; @@ -185,9 +185,9 @@ pub struct RustTypeBuilder<'env> { env: &'env Env, type_id: library::TypeId, direction: ParameterDirection, - nullable: Nullable, + nullable: bool, ref_mode: RefMode, - scope: ParameterScope, + scope: Option, concurrency: library::Concurrency, try_from_glib: TryFromGlib, callback_parameters_config: CallbackParameters, @@ -199,9 +199,9 @@ impl<'env> RustTypeBuilder<'env> { env, type_id, direction: ParameterDirection::None, - nullable: Nullable(false), + nullable: false, ref_mode: RefMode::None, - scope: ParameterScope::None, + scope: None, concurrency: library::Concurrency::None, try_from_glib: TryFromGlib::default(), callback_parameters_config: Vec::new(), @@ -213,7 +213,7 @@ impl<'env> RustTypeBuilder<'env> { self } - pub fn nullable(mut self, nullable: Nullable) -> Self { + pub fn nullable(mut self, nullable: bool) -> Self { self.nullable = nullable; self } @@ -223,7 +223,7 @@ impl<'env> RustTypeBuilder<'env> { self } - pub fn scope(mut self, scope: ParameterScope) -> Self { + pub fn scope(mut self, scope: Option) -> Self { self.scope = scope; self } @@ -427,7 +427,7 @@ impl<'env> RustTypeBuilder<'env> { } Function(ref f) => { let concurrency = match self.concurrency { - _ if self.scope.is_call() => "", + _ if self.scope.is_some_and(|s| s.is_call()) => "", library::Concurrency::Send => " + Send", // If an object is Sync, it can be shared between threads, and as // such our callback can be called from arbitrary threads and needs @@ -450,35 +450,35 @@ impl<'env> RustTypeBuilder<'env> { let mut params = Vec::with_capacity(f.parameters.len()); let mut err = false; for p in &f.parameters { - if p.closure.is_some() { + if p.closure().is_some() { continue; } let nullable = self .callback_parameters_config .iter() - .find(|cp| cp.ident.is_match(&p.name)) + .find(|cp| cp.ident.is_match(p.name())) .and_then(|c| c.nullable) - .unwrap_or(p.nullable); - let p_res = RustType::builder(self.env, p.typ) - .direction(p.direction) + .unwrap_or(p.is_nullable()); + let p_res = RustType::builder(self.env, p.typ()) + .direction(p.direction()) .nullable(nullable) .try_build(); match p_res { Ok(p_rust_type) => { - let is_basic = p.typ.is_basic_type(self.env); - let y = RustType::try_new(self.env, p.typ) + let is_basic = p.typ().is_basic_type(self.env); + let y = RustType::try_new(self.env, p.typ()) .unwrap_or_else(|_| RustType::default()); params.push(format!( "{}{}", - if is_basic || *nullable { "" } else { "&" }, + if is_basic || nullable { "" } else { "&" }, if !is_gstring(y.as_str()) { - if !is_basic && *nullable { + if !is_basic && nullable { p_rust_type.into_string().replace("Option<", "Option<&") } else { p_rust_type.into_string() } - } else if *nullable { + } else if nullable { "Option<&str>".to_owned() } else { "&str".to_owned() @@ -491,20 +491,20 @@ impl<'env> RustTypeBuilder<'env> { } } } - let closure_kind = if self.scope.is_call() { + let closure_kind = if self.scope.is_some_and(|s| s.is_call()) { "FnMut" - } else if self.scope.is_async() { + } else if self.scope.is_some_and(|s| s.is_async()) { "FnOnce" } else { "Fn" }; - let ret_res = RustType::builder(self.env, f.ret.typ) - .direction(f.ret.direction) - .nullable(f.ret.nullable) + let ret_res = RustType::builder(self.env, f.ret.typ()) + .direction(f.ret.direction()) + .nullable(f.ret.is_nullable()) .try_build(); let ret = match ret_res { Ok(ret_rust_type) => { - let y = RustType::try_new(self.env, f.ret.typ) + let y = RustType::try_new(self.env, f.ret.typ()) .unwrap_or_else(|_| RustType::default()); format!( "{}({}) -> {}{}", @@ -512,7 +512,7 @@ impl<'env> RustTypeBuilder<'env> { params.join(", "), if !is_gstring(y.as_str()) { ret_rust_type.as_str() - } else if *f.ret.nullable { + } else if f.ret.is_nullable() { "Option" } else { "String" @@ -537,8 +537,8 @@ impl<'env> RustTypeBuilder<'env> { if err { return Err(TypeError::Unimplemented(ret)); } - Ok(if *self.nullable { - if self.scope.is_call() { + Ok(if self.nullable { + if self.scope.is_some_and(|s| s.is_call()) { format!("Option<&mut dyn {ret}>") } else { format!("Option>") @@ -547,7 +547,7 @@ impl<'env> RustTypeBuilder<'env> { format!( "{}{}", ret, - if self.scope.is_call() { + if self.scope.is_some_and(|s| s.is_call()) { "" } else { " + 'static" @@ -604,7 +604,7 @@ impl<'env> RustTypeBuilder<'env> { } } - if *self.nullable && !skip_option { + if self.nullable && !skip_option { match ConversionType::of(self.env, self.type_id) { ConversionType::Pointer | ConversionType::Scalar => { rust_type = rust_type.map_any(|rust_type| { diff --git a/src/analysis/safety_assertion_mode.rs b/src/analysis/safety_assertion_mode.rs index f457db23a..a9051e454 100644 --- a/src/analysis/safety_assertion_mode.rs +++ b/src/analysis/safety_assertion_mode.rs @@ -48,7 +48,7 @@ impl SafetyAssertionMode { let c_par = ¶ms.c_parameters[par.ind_c]; match env.library.type_(c_par.typ) { Class(..) | Interface(..) - if !*c_par.nullable && c_par.typ.ns_id == library::MAIN_NAMESPACE => + if !c_par.nullable && c_par.typ.ns_id == library::MAIN_NAMESPACE => { return Self::Skip; } diff --git a/src/analysis/signatures.rs b/src/analysis/signatures.rs index 4a372d708..c0118118a 100644 --- a/src/analysis/signatures.rs +++ b/src/analysis/signatures.rs @@ -7,8 +7,8 @@ pub struct Signature(Vec, library::TypeId, Option); impl Signature { pub fn new(func: &library::Function) -> Self { - let params = func.parameters.iter().map(|p| p.typ).collect(); - Self(params, func.ret.typ, func.version) + let params = func.parameters.iter().map(|p| p.typ()).collect(); + Self(params, func.ret.typ(), func.version) } fn from_property(is_get: bool, typ: library::TypeId) -> Self { diff --git a/src/analysis/special_functions.rs b/src/analysis/special_functions.rs index 7aa2852f2..b1df35e9f 100644 --- a/src/analysis/special_functions.rs +++ b/src/analysis/special_functions.rs @@ -90,12 +90,12 @@ fn is_stringify(func: &mut FuncInfo, parent_type: &LibType, obj: &GObject) -> bo if func.parameters.c_parameters.len() != 1 { return false; } - if !func.parameters.c_parameters[0].instance_parameter { + if !func.parameters.c_parameters[0].is_instance_parameter { return false; } if let Some(ret) = func.ret.parameter.as_mut() { - if ret.lib_par.typ != TypeId::tid_utf8() { + if ret.lib_par.typ() != TypeId::tid_utf8() { return false; } @@ -113,12 +113,12 @@ fn is_stringify(func: &mut FuncInfo, parent_type: &LibType, obj: &GObject) -> bo if !obj.trust_return_value_nullability && !matches!(parent_type, LibType::Enumeration(_) | LibType::Bitfield(_)) { - *ret.lib_par.nullable = false; + ret.lib_par.set_nullable(false); } } // Cannot generate Display implementation for Option<> - !*ret.lib_par.nullable + !ret.lib_par.is_nullable() } else { false } @@ -148,7 +148,7 @@ pub fn extract(functions: &mut [FuncInfo], parent_type: &LibType, obj: &GObject) .ret .parameter .as_ref() - .is_some_and(|ret| ret.lib_par.transfer == crate::library::Transfer::None); + .is_some_and(|ret| ret.lib_par.transfer_ownership().is_none()); // Assume only enumerations and bitfields can return static strings let returns_static_ref = return_transfer_none diff --git a/src/analysis/symbols.rs b/src/analysis/symbols.rs index 88d5640a7..024b9191c 100644 --- a/src/analysis/symbols.rs +++ b/src/analysis/symbols.rs @@ -179,7 +179,7 @@ pub fn run(library: &Library, namespaces: &namespaces::Info) -> Info { name: func.name.clone(), ..Default::default() }; - info.insert(func.c_identifier.as_ref().unwrap(), symbol, None); + info.insert(&func.c_identifier, symbol, None); } } Type::Record(Record { @@ -208,7 +208,7 @@ pub fn run(library: &Library, namespaces: &namespaces::Info) -> Info { name: func.name.clone(), ..Default::default() }; - info.insert(func.c_identifier.as_ref().unwrap(), symbol, None); + info.insert(&func.c_identifier, symbol, None); } } _ => {} diff --git a/src/analysis/trampoline_parameters.rs b/src/analysis/trampoline_parameters.rs index d3071c000..da2afd70f 100644 --- a/src/analysis/trampoline_parameters.rs +++ b/src/analysis/trampoline_parameters.rs @@ -14,7 +14,7 @@ pub struct RustParameter { pub name: String, pub typ: library::TypeId, pub direction: library::ParameterDirection, - pub nullable: library::Nullable, + pub nullable: bool, pub ref_mode: RefMode, pub try_from_glib: TryFromGlib, } @@ -39,7 +39,7 @@ pub struct Transformation { pub transformation: TransformationType, pub name: String, pub typ: library::TypeId, - pub transfer: library::Transfer, + pub transfer: gir_parser::TransferOwnership, pub ref_mode: RefMode, pub conversion_type: ConversionType, } @@ -65,17 +65,17 @@ impl Parameters { env: &Env, type_tid: library::TypeId, name: String, - c_type: String, + c_type: &str, direction: library::ParameterDirection, - transfer: library::Transfer, - nullable: library::Nullable, + transfer: gir_parser::TransferOwnership, + nullable: bool, ref_mode: RefMode, conversion_type: ConversionType, ) -> Transformation { let c_par = CParameter { name: name.clone(), typ: type_tid, - c_type, + c_type: c_type.to_owned(), }; let ind_c = self.c_parameters.len(); self.c_parameters.push(c_par); @@ -126,17 +126,17 @@ pub fn analyze( env, type_tid, "this".to_owned(), - c_type, + &c_type, library::ParameterDirection::In, - library::Transfer::None, - library::Nullable(false), + gir_parser::TransferOwnership::None, + false, RefMode::ByRef, ConversionType::Borrow, ); parameters.transformations.push(transform); for par in signal_parameters { - let name = nameutil::mangle_keywords(&*par.name).into_owned(); + let name = nameutil::mangle_keywords(par.name()).into_owned(); let ref_mode = RefMode::without_unneeded_mut(env, par, false, false); @@ -147,19 +147,19 @@ pub fn analyze( .or_else(|| { callback_parameters_config.and_then(|cp| { cp.iter() - .find(|cp| cp.ident.is_match(&par.name)) + .find(|cp| cp.ident.is_match(par.name())) .and_then(|c| c.nullable) }) }); - let nullable = nullable_override.unwrap_or(par.nullable); + let nullable = nullable_override.unwrap_or(par.is_nullable()); let conversion_type = { - match env.library.type_(par.typ) { + match env.library.type_(par.typ()) { library::Type::Basic(library::Basic::Utf8) | library::Type::Record(..) | library::Type::Interface(..) | library::Type::Class(..) => ConversionType::Borrow, - _ => ConversionType::of(env, par.typ), + _ => ConversionType::of(env, par.typ()), } }; @@ -174,11 +174,11 @@ pub fn analyze( let mut transform = parameters.prepare_transformation( env, - par.typ, + par.typ(), name, - par.c_type.clone(), - par.direction, - par.transfer, + par.c_type(), + par.direction(), + par.transfer_ownership(), nullable, ref_mode, conversion_type, diff --git a/src/analysis/trampolines.rs b/src/analysis/trampolines.rs index 0af8ac4fc..c5ff7ba3a 100644 --- a/src/analysis/trampolines.rs +++ b/src/analysis/trampolines.rs @@ -33,11 +33,11 @@ pub struct Trampoline { pub inhibit: bool, pub concurrency: library::Concurrency, pub is_notify: bool, - pub scope: library::ParameterScope, + pub scope: Option, /// It's used to group callbacks pub user_data_index: usize, pub destroy_index: usize, - pub nullable: library::Nullable, + pub nullable: bool, /// This field is used to give the type name when generating the "IsA" /// part. pub type_name: String, @@ -73,7 +73,7 @@ pub fn analyze( // TODO: move to object.signal.return config let inhibit = configured_signals.iter().any(|f| f.inhibit); - if inhibit && signal.ret.typ != library::TypeId::tid_bool() { + if inhibit && signal.ret.typ() != library::TypeId::tid_bool() { error!("Wrong return type for Inhibit for signal '{}'", signal.name); } @@ -110,10 +110,10 @@ pub fn analyze( env, type_tid, "this".to_owned(), - c_type, + &c_type, library::ParameterDirection::In, - library::Transfer::None, - library::Nullable(false), + gir_parser::TransferOwnership::None, + false, crate::analysis::ref_mode::RefMode::ByRef, ConversionType::Borrow, ); @@ -160,17 +160,17 @@ pub fn analyze( } } - let mut ret_nullable = signal.ret.nullable; + let mut ret_nullable = signal.ret.is_nullable(); - if signal.ret.typ != Default::default() { - if let Ok(rust_type) = RustType::builder(env, signal.ret.typ) + if signal.ret.typ() != Default::default() { + if let Ok(rust_type) = RustType::builder(env, signal.ret.typ()) .direction(library::ParameterDirection::Out) .try_build() { // No GString used_types.extend(rust_type.into_used_types()); } - if let Some(ffi_type) = used_ffi_type(env, signal.ret.typ, &signal.ret.c_type) { + if let Some(ffi_type) = used_ffi_type(env, signal.ret.typ(), signal.ret.c_type()) { used_types.push(ffi_type); } @@ -186,10 +186,8 @@ pub fn analyze( .next() .unwrap_or(obj.concurrency); - let ret = library::Parameter { - nullable: ret_nullable, - ..signal.ret.clone() - }; + let mut ret = signal.ret.clone(); + ret.set_nullable(ret_nullable); let trampoline = Trampoline { name, @@ -201,10 +199,10 @@ pub fn analyze( concurrency, is_notify, bound_name: String::new(), - scope: library::ParameterScope::None, + scope: None, user_data_index: 0, destroy_index: 0, - nullable: library::Nullable(false), + nullable: false, type_name: env.library.type_(type_tid).get_name(), }; Ok(trampoline) @@ -217,18 +215,18 @@ fn closure_errors(env: &Env, signal: &library::Signal) -> Vec { errors.push(format!( "{} {}: {}", error, - par.name, - par.typ.full_name(&env.library) + par.name(), + par.typ().full_name(&env.library) )); } } - if signal.ret.typ != Default::default() + if signal.ret.typ() != Default::default() && let Some(error) = type_error(env, &signal.ret) { errors.push(format!( "{} return value {}", error, - signal.ret.typ.full_name(&env.library) + signal.ret.typ().full_name(&env.library) )); } errors @@ -236,16 +234,16 @@ fn closure_errors(env: &Env, signal: &library::Signal) -> Vec { pub fn type_error(env: &Env, par: &library::Parameter) -> Option<&'static str> { use super::rust_type::TypeError::*; - if par.direction == library::ParameterDirection::Out { + if par.direction().is_out() { Some("Out") - } else if par.direction == library::ParameterDirection::InOut { + } else if par.direction() == library::ParameterDirection::InOut { Some("InOut") - } else if is_empty_c_type(&par.c_type) { + } else if is_empty_c_type(par.c_type()) { Some("Empty ctype") - } else if ConversionType::of(env, par.typ) == ConversionType::Unknown { + } else if ConversionType::of(env, par.typ()) == ConversionType::Unknown { Some("Unknown conversion") } else { - match RustType::try_new(env, par.typ) { + match RustType::try_new(env, par.typ()) { Err(Ignored(_)) => Some("Ignored"), Err(Mismatch(_)) => Some("Mismatch"), Err(Unimplemented(_)) => Some("Unimplemented"), diff --git a/src/analysis/types.rs b/src/analysis/types.rs index 4bd32bc4c..1b26da108 100644 --- a/src/analysis/types.rs +++ b/src/analysis/types.rs @@ -128,7 +128,7 @@ impl IsIncomplete for Function { // Checking p.typ.is_incomplete(lib) cause recursive check on GScannerMsgFunc self.parameters.iter().any(|p| { matches!( - lib.type_(p.typ), + lib.type_(p.typ()), Type::Basic(Basic::Unsupported | Basic::VarArgs) ) }) diff --git a/src/chunk/conversion_from_glib.rs b/src/chunk/conversion_from_glib.rs index 394fb82c6..1bf66b7c2 100644 --- a/src/chunk/conversion_from_glib.rs +++ b/src/chunk/conversion_from_glib.rs @@ -7,7 +7,7 @@ use crate::{ #[derive(Clone, Debug)] pub struct Mode { pub typ: library::TypeId, - pub transfer: library::Transfer, + pub transfer: gir_parser::TransferOwnership, pub try_from_glib: TryFromGlib, } @@ -24,8 +24,8 @@ impl From<¶meter_ffi_call_out::Parameter> for Mode { impl From<&analysis::Parameter> for Mode { fn from(orig: &analysis::Parameter) -> Mode { Mode { - typ: orig.lib_par.typ, - transfer: orig.lib_par.transfer, + typ: orig.lib_par.typ(), + transfer: orig.lib_par.transfer_ownership(), try_from_glib: orig.try_from_glib.clone(), } } diff --git a/src/chunk/parameter_ffi_call_out.rs b/src/chunk/parameter_ffi_call_out.rs index aeaea2277..b078b0728 100644 --- a/src/chunk/parameter_ffi_call_out.rs +++ b/src/chunk/parameter_ffi_call_out.rs @@ -7,7 +7,7 @@ use crate::{ pub struct Parameter { pub name: String, pub typ: library::TypeId, - pub transfer: library::Transfer, + pub transfer: gir_parser::TransferOwnership, pub caller_allocates: bool, pub is_error: bool, pub is_uninitialized: bool, @@ -31,11 +31,11 @@ impl Parameter { impl From<&analysis::Parameter> for Parameter { fn from(orig: &analysis::Parameter) -> Self { Self { - name: orig.lib_par.name.clone(), - typ: orig.lib_par.typ, - transfer: orig.lib_par.transfer, - caller_allocates: orig.lib_par.caller_allocates, - is_error: orig.lib_par.is_error, + name: orig.lib_par.name().to_owned(), + typ: orig.lib_par.typ(), + transfer: orig.lib_par.transfer_ownership(), + caller_allocates: orig.lib_par.is_caller_allocates(), + is_error: orig.lib_par.is_error(), is_uninitialized: false, try_from_glib: orig.try_from_glib.clone(), } diff --git a/src/codegen/bound.rs b/src/codegen/bound.rs index 7a5d998aa..11a9b235b 100644 --- a/src/codegen/bound.rs +++ b/src/codegen/bound.rs @@ -1,9 +1,6 @@ -use crate::{ - analysis::{ - bounds::{Bound, BoundType}, - ref_mode::RefMode, - }, - library::Nullable, +use crate::analysis::{ + bounds::{Bound, BoundType}, + ref_mode::RefMode, }; impl Bound { @@ -18,7 +15,7 @@ impl Bound { pub(super) fn full_type_parameter_reference( &self, ref_mode: RefMode, - nullable: Nullable, + nullable: bool, r#async: bool, ) -> String { let ref_str = ref_mode.for_rust_type(); @@ -48,11 +45,11 @@ impl Bound { }; match self.bound_type { - BoundType::IsA(_) if *nullable => { + BoundType::IsA(_) if nullable => { format!("Option<{ref_str}{trait_bound}>") } BoundType::IsA(_) => format!("{ref_str}{trait_bound}"), - BoundType::AsRef(_) if *nullable => { + BoundType::AsRef(_) if nullable => { format!("Option<{trait_bound}>") } BoundType::NoWrapper | BoundType::AsRef(_) => trait_bound, diff --git a/src/codegen/doc/format.rs b/src/codegen/doc/format.rs index da90b3f0c..0b01a2582 100644 --- a/src/codegen/doc/format.rs +++ b/src/codegen/doc/format.rs @@ -10,7 +10,6 @@ use crate::{ analysis::functions::Info, library::{FunctionKind, TypeId}, nameutil, - parser::DocFormat, }; const LANGUAGE_SEP_BEGIN: &str = " - - "#; - - assert!(parse_with_root_name(xml, "a").is_ok()); - assert!(parse_with_root_name(xml, "b").is_err()); - } - - #[test] - fn test_ignore_element() { - let xml = br#" - - - - - - some text content - "#; - - with_parser(xml, |mut p| { - p.document(|p, _| p.element_with_name("a", |p, _| p.ignore_element())) - }) - .unwrap(); - } - - #[test] - fn test_elements() { - let xml = br#" - - - - - "#; - - let result: String = with_parser(xml, |mut p| { - p.document(|p, _| { - p.element_with_name("root", |p, _| { - p.elements(|_, elem| elem.attr_required("name").map(|s| s.to_owned())) - .map(|v| v.join(".")) - }) - }) - }) - .unwrap(); - - assert_eq!("a.b.c", result); - } - - #[test] - fn test_text() { - let xml = br#" - hello world!"#; - - let result: String = with_parser(xml, |mut p| { - p.document(|p, _| p.element_with_name("x", |p, _| p.text())) - }) - .unwrap(); - - assert_eq!("hello world!", &result); - } - - #[test] - fn test_attr_required() { - let xml = br#" - "#; - - with_parser(xml, |mut p| { - p.document(|p, _| { - p.element_with_name("x", |_, elem| { - assert!(elem.attr_required("a").is_ok()); - assert!(elem.attr_required("b").is_ok()); - assert!(elem.attr_required("c").is_err()); - assert!(elem.attr_required("d").is_err()); - Ok(()) - }) - }) - }) - .unwrap(); - } - - #[test] - fn test_attr_from_str() { - let xml = br#" - "#; - - with_parser(xml, |mut p| { - p.document(|p, _| { - p.element_with_name("x", |_, elem| { - assert_eq!(elem.attr_from_str::("a").unwrap(), Some(123)); - assert!(elem.attr_from_str::("b").is_err()); - Ok(()) - }) - }) - }) - .unwrap(); - } -}