Skip to content

Commit

Permalink
Implement support for inline allocated Boxed types
Browse files Browse the repository at this point in the history
Useful for graphene and code reduction in various other places.

See gtk-rs/gtk-rs-core#211
  • Loading branch information
sdroege committed Oct 9, 2021
1 parent 3add890 commit f1253e9
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 14 deletions.
12 changes: 11 additions & 1 deletion src/analysis/record.rs
Expand Up @@ -19,7 +19,9 @@ pub struct Info {
pub glib_get_type: Option<(String, Option<Version>)>,
pub is_boxed: bool,
pub derives: Derives,
pub boxed_inline: bool,
pub init_function_expression: Option<String>,
pub copy_into_function_expression: Option<String>,
pub clear_function_expression: Option<String>,
}

Expand Down Expand Up @@ -78,6 +80,7 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
let record: &library::Record = type_.maybe_ref()?;

let is_boxed = RecordType::of(record) == RecordType::AutoBoxed;
let boxed_inline = obj.boxed_inline;

let mut imports = Imports::with_defined(&env.library, &name);

Expand Down Expand Up @@ -105,8 +108,11 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
};

let mut derives = if let Some(ref derives) = obj.derives {
if boxed_inline {
panic!("Can't automatically derive traits for BoxedInline records");
}
derives.clone()
} else {
} else if !boxed_inline {
let derives = vec![Derive {
names: vec![
"Debug".into(),
Expand All @@ -120,6 +126,8 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
}];

derives
} else {
vec![]
};

for special in specials.traits().keys() {
Expand Down Expand Up @@ -196,7 +204,9 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
glib_get_type,
derives,
is_boxed,
boxed_inline,
init_function_expression: obj.init_function_expression.clone(),
copy_into_function_expression: obj.copy_into_function_expression.clone(),
clear_function_expression: obj.clear_function_expression.clone(),
};

Expand Down
54 changes: 44 additions & 10 deletions src/codegen/general.rs
Expand Up @@ -224,7 +224,9 @@ fn define_boxed_type_internal(
glib_name: &str,
copy_fn: &TraitInfo,
free_fn: &str,
boxed_inline: bool,
init_function_expression: &Option<String>,
copy_into_function_expression: &Option<String>,
clear_function_expression: &Option<String>,
get_type_fn: Option<&str>,
derive: &[Derive],
Expand All @@ -235,8 +237,11 @@ fn define_boxed_type_internal(
derives(w, derive, 1)?;
writeln!(
w,
"\tpub struct {}(Boxed<{}::{}>);",
type_name, sys_crate_name, glib_name
"\tpub struct {}(Boxed{}<{}::{}>);",
type_name,
if boxed_inline { "Inline" } else { "" },
sys_crate_name,
glib_name
)?;
writeln!(w)?;
writeln!(w, "\tmatch fn {{")?;
Expand All @@ -252,10 +257,17 @@ fn define_boxed_type_internal(
)?;
writeln!(w, "\t\tfree => |ptr| {}::{}(ptr),", sys_crate_name, free_fn)?;

if let (Some(init_function_expression), Some(clear_function_expression)) =
(init_function_expression, clear_function_expression)
{
if let (
Some(init_function_expression),
Some(copy_into_function_expression),
Some(clear_function_expression),
) = (
init_function_expression,
copy_into_function_expression,
clear_function_expression,
) {
writeln!(w, "\t\tinit => {},", init_function_expression,)?;
writeln!(w, "\t\tcopy_into => {},", copy_into_function_expression,)?;
writeln!(w, "\t\tclear => {},", clear_function_expression,)?;
}

Expand All @@ -275,7 +287,9 @@ pub fn define_boxed_type(
glib_name: &str,
copy_fn: &TraitInfo,
free_fn: &str,
boxed_inline: bool,
init_function_expression: &Option<String>,
copy_into_function_expression: &Option<String>,
clear_function_expression: &Option<String>,
get_type_fn: Option<(String, Option<Version>)>,
derive: &[Derive],
Expand All @@ -292,7 +306,9 @@ pub fn define_boxed_type(
glib_name,
copy_fn,
free_fn,
boxed_inline,
init_function_expression,
copy_into_function_expression,
clear_function_expression,
Some(get_type_fn),
derive,
Expand All @@ -307,7 +323,9 @@ pub fn define_boxed_type(
glib_name,
copy_fn,
free_fn,
boxed_inline,
init_function_expression,
copy_into_function_expression,
clear_function_expression,
None,
derive,
Expand All @@ -320,7 +338,9 @@ pub fn define_boxed_type(
glib_name,
copy_fn,
free_fn,
boxed_inline,
init_function_expression,
copy_into_function_expression,
clear_function_expression,
Some(get_type_fn),
derive,
Expand All @@ -334,7 +354,9 @@ pub fn define_boxed_type(
glib_name,
copy_fn,
free_fn,
boxed_inline,
init_function_expression,
copy_into_function_expression,
clear_function_expression,
None,
derive,
Expand All @@ -349,7 +371,9 @@ pub fn define_auto_boxed_type(
env: &Env,
type_name: &str,
glib_name: &str,
boxed_inline: bool,
init_function_expression: &Option<String>,
copy_into_function_expression: &Option<String>,
clear_function_expression: &Option<String>,
get_type_fn: &str,
derive: &[Derive],
Expand All @@ -360,8 +384,11 @@ pub fn define_auto_boxed_type(
derives(w, derive, 1)?;
writeln!(
w,
"\tpub struct {}(Boxed<{}::{}>);",
type_name, sys_crate_name, glib_name
"\tpub struct {}(Boxed{}<{}::{}>);",
type_name,
if boxed_inline { "Inline" } else { "" },
sys_crate_name,
glib_name
)?;
writeln!(w)?;
writeln!(w, "\tmatch fn {{")?;
Expand All @@ -382,10 +409,17 @@ pub fn define_auto_boxed_type(
get_type_fn
)?;

if let (Some(init_function_expression), Some(clear_function_expression)) =
(init_function_expression, clear_function_expression)
{
if let (
Some(init_function_expression),
Some(copy_into_function_expression),
Some(clear_function_expression),
) = (
init_function_expression,
copy_into_function_expression,
clear_function_expression,
) {
writeln!(w, "\t\tinit => {},", init_function_expression,)?;
writeln!(w, "\t\tcopy_into => {},", copy_into_function_expression,)?;
writeln!(w, "\t\tclear => {},", clear_function_expression,)?;
}

Expand Down
4 changes: 4 additions & 0 deletions src/codegen/record.rs
Expand Up @@ -19,7 +19,9 @@ pub fn generate(w: &mut dyn Write, env: &Env, analysis: &analysis::record::Info)
env,
&analysis.name,
&type_.c_type,
analysis.boxed_inline,
&analysis.init_function_expression,
&analysis.copy_into_function_expression,
&analysis.clear_function_expression,
glib_get_type,
&analysis.derives,
Expand Down Expand Up @@ -61,7 +63,9 @@ pub fn generate(w: &mut dyn Write, env: &Env, analysis: &analysis::record::Info)
&type_.c_type,
copy_fn,
&free_fn.glib_name,
analysis.boxed_inline,
&analysis.init_function_expression,
&analysis.copy_into_function_expression,
&analysis.clear_function_expression,
analysis.glib_get_type.as_ref().map(|(f, v)| {
if v > &analysis.version {
Expand Down
38 changes: 35 additions & 3 deletions src/config/gobjects.rs
Expand Up @@ -90,7 +90,9 @@ pub struct GObject {
pub align: Option<u32>,
pub generate_builder: bool,
pub builder_postprocess: Option<String>,
pub boxed_inline: bool,
pub init_function_expression: Option<String>,
pub copy_into_function_expression: Option<String>,
pub clear_function_expression: Option<String>,
}

Expand Down Expand Up @@ -122,7 +124,9 @@ impl Default for GObject {
align: None,
generate_builder: false,
builder_postprocess: None,
boxed_inline: false,
init_function_expression: None,
copy_into_function_expression: None,
clear_function_expression: None,
}
}
Expand Down Expand Up @@ -270,7 +274,9 @@ fn parse_object(
"align",
"generate_builder",
"builder_postprocess",
"boxed_inline",
"init_function_expression",
"copy_into_function_expression",
"clear_function_expression",
],
&format!("object {}", name),
Expand Down Expand Up @@ -380,6 +386,11 @@ fn parse_object(
.and_then(Value::as_bool)
.unwrap_or(generate_builder);

let boxed_inline = toml_object
.lookup("boxed_inline")
.and_then(Value::as_bool)
.unwrap_or(false);

let builder_postprocess = toml_object
.lookup("builder_postprocess")
.and_then(Value::as_str)
Expand All @@ -388,16 +399,35 @@ fn parse_object(
.lookup("init_function_expression")
.and_then(Value::as_str)
.map(ToOwned::to_owned);
let copy_into_function_expression = toml_object
.lookup("copy_into_function_expression")
.and_then(Value::as_str)
.map(ToOwned::to_owned);
let clear_function_expression = toml_object
.lookup("clear_function_expression")
.and_then(Value::as_str)
.map(ToOwned::to_owned);

if (init_function_expression.is_some() && clear_function_expression.is_none())
|| (init_function_expression.is_none() && clear_function_expression.is_some())
if boxed_inline
&& !((init_function_expression.is_none()
&& copy_into_function_expression.is_none()
&& clear_function_expression.is_none())
|| (init_function_expression.is_some()
&& copy_into_function_expression.is_some()
&& clear_function_expression.is_some()))
{
panic!(
"`init_function_expression`, `copy_into_function_expression` and `clear_function_expression` all have to be provided or neither"
);
}

if !boxed_inline
&& (init_function_expression.is_some()
|| copy_into_function_expression.is_some()
|| clear_function_expression.is_some())
{
panic!(
"`init_function_expression` and `clear_function_expression` both have to be provided"
"`init_function_expression`, `copy_into_function_expression` and `clear_function_expression` can only be provided for BoxedInline types"
);
}

Expand Down Expand Up @@ -449,7 +479,9 @@ fn parse_object(
align,
generate_builder,
builder_postprocess,
boxed_inline,
init_function_expression,
copy_into_function_expression,
clear_function_expression,
}
}
Expand Down

0 comments on commit f1253e9

Please sign in to comment.