Skip to content

Commit

Permalink
Merge pull request #1294 from bilelmoussaoui/bilelmoussaoui/fundemant…
Browse files Browse the repository at this point in the history
…al-types

support fundamental types
  • Loading branch information
sdroege authored Jan 1, 2022
2 parents 8fcb6df + c20fe52 commit bb0022f
Show file tree
Hide file tree
Showing 12 changed files with 244 additions and 42 deletions.
5 changes: 5 additions & 0 deletions book/src/config_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ child_name = "item"
# will not generate trait SomeClassExt for this object, but implement all
# functions in impl SomeClass
final_type = true
# mark the object as a fundamental type in case the GIR file lacks the annotation
# note that fundamental types don't make use of IsA/Cast traits and you should
# implement something similar manually
# gir is only capable for generating the type definitions along with their functions
fundamental_type = false
# allow rename result file
module_name = "soome_class"
# override starting version
Expand Down
4 changes: 4 additions & 0 deletions src/analysis/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ impl Bounds {
use self::BoundType::*;
match env.library.type_(type_id) {
Type::Fundamental(Fundamental::Filename | Fundamental::OsString) => Some(AsRef(None)),
Type::Class(Class {
is_fundamental: true,
..
}) => Some(AsRef(None)),
Type::Class(Class {
final_type: true, ..
}) => None,
Expand Down
29 changes: 27 additions & 2 deletions src/analysis/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct Info {
pub c_class_type: Option<String>,
pub get_type: String,
pub is_interface: bool,
pub is_fundamental: bool,
pub supertypes: Vec<general::StatusedTypeId>,
pub final_type: bool,
pub generate_trait: bool,
Expand All @@ -41,6 +42,10 @@ pub struct Info {
pub builder_postprocess: Option<String>,
pub child_properties: ChildProperties,
pub signatures: Signatures,
/// Specific to fundamental types
pub ref_fn: Option<String>,
/// Specific to fundamental types
pub unref_fn: Option<String>,
}

impl Info {
Expand Down Expand Up @@ -163,6 +168,7 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
.as_ref()
.cloned()
.unwrap_or_else(|| format!("{}Ext", name));
let is_fundamental = obj.fundamental_type.unwrap_or(klass.is_fundamental);

let mut signatures = Signatures::with_capacity(klass.functions.len());

Expand Down Expand Up @@ -197,6 +203,7 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
&klass.signals,
class_tid,
!final_type,
is_fundamental,
obj,
&mut imports,
);
Expand All @@ -205,6 +212,7 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
&klass.properties,
class_tid,
!final_type,
is_fundamental,
obj,
&mut imports,
&signatures,
Expand All @@ -222,14 +230,19 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
.any(|f| f.kind == library::FunctionKind::Method && f.status.need_generate());
let has_signals = signals.iter().any(|s| s.trampoline.is_ok())
|| notify_signals.iter().any(|s| s.trampoline.is_ok());

// There's no point in generating a trait if there are no signals, methods, properties
// and child properties: it would be empty
//
// There's also no point in generating a trait for final types: there are no possible subtypes
let generate_trait = !final_type
&& !is_fundamental
&& (has_signals || has_methods || !properties.is_empty() || !child_properties.is_empty());

if is_fundamental {
imports.add("glib::StaticType");
imports.add("glib::translate::*");
}

if has_builder_properties(&builder_properties) {
imports.add("glib::object::Cast");
imports.add("glib::StaticType");
Expand Down Expand Up @@ -277,6 +290,7 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
c_class_type: klass.c_class_type.clone(),
get_type: klass.glib_get_type.clone(),
is_interface: false,
is_fundamental,
supertypes,
final_type,
generate_trait,
Expand All @@ -290,6 +304,8 @@ pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info>
builder_postprocess: obj.builder_postprocess.clone(),
child_properties,
signatures,
ref_fn: klass.ref_fn.clone(),
unref_fn: klass.unref_fn.clone(),
};

Some(info)
Expand Down Expand Up @@ -338,12 +354,21 @@ pub fn interface(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<I
Some(deps),
);

let signals = signals::analyze(env, &iface.signals, iface_tid, true, obj, &mut imports);
let signals = signals::analyze(
env,
&iface.signals,
iface_tid,
true,
false,
obj,
&mut imports,
);
let (properties, notify_signals) = properties::analyze(
env,
&iface.properties,
iface_tid,
true,
false,
obj,
&mut imports,
&signatures,
Expand Down
4 changes: 4 additions & 0 deletions src/analysis/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub fn analyze(
props: &[library::Property],
type_tid: library::TypeId,
generate_trait: bool,
is_fundamental: bool,
obj: &GObject,
imports: &mut Imports,
signatures: &Signatures,
Expand Down Expand Up @@ -65,6 +66,7 @@ pub fn analyze(
type_tid,
&configured_properties,
generate_trait,
is_fundamental,
obj,
imports,
signatures,
Expand Down Expand Up @@ -92,6 +94,7 @@ fn analyze_property(
type_tid: library::TypeId,
configured_properties: &[&config::properties::Property],
generate_trait: bool,
is_fundamental: bool,
obj: &GObject,
imports: &mut Imports,
signatures: &Signatures,
Expand Down Expand Up @@ -319,6 +322,7 @@ fn analyze_property(
},
type_tid,
generate_trait,
is_fundamental,
&[],
obj,
&mut used_types,
Expand Down
4 changes: 4 additions & 0 deletions src/analysis/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn analyze(
signals: &[library::Signal],
type_tid: library::TypeId,
in_trait: bool,
is_fundamental: bool,
obj: &GObject,
imports: &mut Imports,
) -> Vec<Info> {
Expand All @@ -44,6 +45,7 @@ pub fn analyze(
signal,
type_tid,
in_trait,
is_fundamental,
&configured_signals,
obj,
imports,
Expand All @@ -59,6 +61,7 @@ fn analyze_signal(
signal: &library::Signal,
type_tid: library::TypeId,
in_trait: bool,
is_fundamental: bool,
configured_signals: &[&config::signals::Signal],
obj: &GObject,
imports: &mut Imports,
Expand All @@ -81,6 +84,7 @@ fn analyze_signal(
signal,
type_tid,
in_trait,
is_fundamental,
configured_signals,
obj,
&mut used_types,
Expand Down
47 changes: 33 additions & 14 deletions src/analysis/trampolines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub fn analyze(
signal: &library::Signal,
type_tid: library::TypeId,
in_trait: bool,
fundamental_type: bool,
configured_signals: &[&config::signals::Signal],
obj: &GObject,
used_types: &mut Vec<String>,
Expand Down Expand Up @@ -76,16 +77,25 @@ pub fn analyze(

let mut bounds: Bounds = Default::default();

if in_trait {
if in_trait || fundamental_type {
let type_name = RustType::builder(env, type_tid)
.ref_mode(RefMode::ByRefFake)
.try_build();
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::IsA(None),
false,
);
if fundamental_type {
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::AsRef(None),
false,
);
} else {
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::IsA(None),
false,
);
}
}

let parameters = if is_notify {
Expand All @@ -112,16 +122,25 @@ pub fn analyze(
trampoline_parameters::analyze(env, &signal.parameters, type_tid, configured_signals, None)
};

if in_trait {
if in_trait || fundamental_type {
let type_name = RustType::builder(env, type_tid)
.ref_mode(RefMode::ByRefFake)
.try_build();
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::IsA(None),
false,
);
if fundamental_type {
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::AsRef(None),
false,
);
} else {
bounds.add_parameter(
"this",
&type_name.into_string(),
BoundType::IsA(None),
false,
);
}
}

for par in &parameters.rust_parameters {
Expand Down
91 changes: 91 additions & 0 deletions src/codegen/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,97 @@ fn format_parent_name(env: &Env, p: &StatusedTypeId) -> String {
}
}

pub fn define_fundamental_type(
w: &mut dyn Write,
env: &Env,
type_name: &str,
glib_name: &str,
glib_func_name: &str,
ref_func: Option<&str>,
unref_func: Option<&str>,
parents: &[StatusedTypeId],
visibility: Visibility,
) -> Result<()> {
let sys_crate_name = env.main_sys_crate_name();
writeln!(w, "{} {{", use_glib_type(env, "wrapper!"))?;
doc_alias(w, glib_name, "", 1)?;
writeln!(
w,
"\t{} struct {}(Shared<{}::{}>);",
visibility, type_name, sys_crate_name, glib_name
)?;
writeln!(w)?;

writeln!(w, "\tmatch fn {{")?;
let (ref_fn, unref_fn, ptr, ffi_crate_name) = if parents.is_empty() {
// it's the super-type, it must have a ref/unref functions
(
ref_func.unwrap().to_owned(),
unref_func.unwrap().to_owned(),
"ptr".to_owned(),
sys_crate_name.to_owned(),
)
} else {
let (ref_fn, unref_fn, ptr, ffi_crate_name) = parents
.iter()
.filter_map(|p| {
use crate::library::*;
let type_ = env.library.type_(p.type_id);
let parent_sys_crate_name = env.sys_crate_import(p.type_id);
match type_ {
Type::Class(class) => Some((
class.ref_fn.as_ref().unwrap().clone(),
class.unref_fn.as_ref().unwrap().clone(),
format!(
"ptr as *mut {}::{}",
parent_sys_crate_name,
class.c_type.clone()
),
parent_sys_crate_name,
)),
_ => None,
}
})
.next()
.unwrap();
// otherwise get that information from the parent
(ref_fn, unref_fn, ptr, ffi_crate_name)
};

writeln!(
w,
"\t\tref => |ptr| {}::{}({}),",
ffi_crate_name, ref_fn, ptr
)?;
writeln!(
w,
"\t\tunref => |ptr| {}::{}({}),",
ffi_crate_name, unref_fn, ptr
)?;

writeln!(w, "\t}}")?;
writeln!(w, "}}")?;

// We can't use type_ from glib::wrapper! because that would auto-implement
// Value traits which are often not the correct types
writeln!(w, "\n")?;
writeln!(
w,
"impl {} for {} {{",
use_glib_type(env, "StaticType"),
type_name
)?;
writeln!(w, "\tfn static_type() -> {} {{", use_glib_type(env, "Type"))?;
writeln!(
w,
"\t\t unsafe {{ from_glib({}::{}()) }}",
sys_crate_name, glib_func_name
)?;
writeln!(w, "\t}}")?;
writeln!(w, "}}")?;
Ok(())
}

pub fn define_object_type(
w: &mut dyn Write,
env: &Env,
Expand Down
Loading

0 comments on commit bb0022f

Please sign in to comment.