Skip to content

Commit 047ecef

Browse files
committed
add a flag for generating variant traits for flags/enums
1 parent 81c03ad commit 047ecef

File tree

5 files changed

+311
-25
lines changed

5 files changed

+311
-25
lines changed

src/codegen/enums.rs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use crate::{
1313
cfg_deprecated, derives, doc_alias, version_condition, version_condition_no_doc,
1414
version_condition_string,
1515
},
16-
generate_default_impl,
16+
generate_default_impl, generate_variant_impls,
1717
},
18-
config::gobjects::GObject,
18+
config::{config::VariantTraitMode, gobjects::GObject},
1919
env::Env,
2020
file_saver,
2121
library::*,
@@ -387,14 +387,14 @@ impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
387387
)?;
388388
}
389389

390+
let configured_functions = config.functions.matched("get_type");
391+
let version = std::iter::once(enum_.version)
392+
.chain(configured_functions.iter().map(|f| f.version))
393+
.max()
394+
.flatten();
395+
390396
// Generate StaticType trait implementation.
391397
if let Some(ref get_type) = enum_.glib_get_type {
392-
let configured_functions = config.functions.matched("get_type");
393-
let version = std::iter::once(enum_.version)
394-
.chain(configured_functions.iter().map(|f| f.version))
395-
.max()
396-
.flatten();
397-
398398
version_condition(w, env, None, version, false, 0)?;
399399
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
400400
allow_deprecated(w, enum_.deprecated_version, false, 0)?;
@@ -506,5 +506,47 @@ impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
506506
},
507507
)?;
508508

509+
match config.generate_variant_traits {
510+
VariantTraitMode::Repr => generate_variant_impls(
511+
w,
512+
env,
513+
config,
514+
&enum_.name,
515+
version,
516+
enum_.deprecated_version,
517+
"i",
518+
"match unsafe { FromGlib::from_glib(variant.get::<i32>()?) } {
519+
Self::__Unknown(_) => None,
520+
value => Some(value),
521+
}",
522+
"self.into_glib().to_variant()",
523+
)?,
524+
VariantTraitMode::String => {
525+
let enumclass = use_glib_type(env, "EnumClass");
526+
generate_variant_impls(
527+
w,
528+
env,
529+
config,
530+
&enum_.name,
531+
version,
532+
enum_.deprecated_version,
533+
"s",
534+
&format!(
535+
"if !variant.is::<String>() {{
536+
return None;
537+
}}
538+
let enum_class = {enumclass}::new(<Self as StaticType>::static_type()).unwrap();
539+
let value = enum_class.value_by_nick(variant.str()?)?.value();
540+
Some(unsafe {{ FromGlib::from_glib(value) }})",
541+
),
542+
&format!(
543+
"let enum_class = {enumclass}::new(<Self as StaticType>::static_type()).unwrap();
544+
enum_class.value(self.into_glib()).unwrap().nick().to_variant()",
545+
)
546+
)?
547+
}
548+
_ => {}
549+
}
550+
509551
Ok(())
510552
}

src/codegen/flags.rs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use crate::{
1212
cfg_deprecated, derives, doc_alias, version_condition, version_condition_doc,
1313
version_condition_no_doc, version_condition_string,
1414
},
15-
generate_default_impl,
15+
generate_default_impl, generate_variant_impls,
1616
},
17-
config::gobjects::GObject,
17+
config::{config::VariantTraitMode, gobjects::GObject},
1818
env::Env,
1919
file_saver,
2020
library::*,
@@ -258,13 +258,13 @@ impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
258258
assert = assert
259259
)?;
260260

261-
if let Some(ref get_type) = flags.glib_get_type {
262-
let configured_functions = config.functions.matched("get_type");
263-
let version = std::iter::once(flags.version)
264-
.chain(configured_functions.iter().map(|f| f.version))
265-
.max()
266-
.flatten();
261+
let configured_functions = config.functions.matched("get_type");
262+
let version = std::iter::once(flags.version)
263+
.chain(configured_functions.iter().map(|f| f.version))
264+
.max()
265+
.flatten();
267266

267+
if let Some(ref get_type) = flags.glib_get_type {
268268
version_condition(w, env, None, version, false, 0)?;
269269
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
270270
allow_deprecated(w, flags.deprecated_version, false, 0)?;
@@ -357,5 +357,43 @@ impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
357357
writeln!(w)?;
358358
}
359359

360+
match config.generate_variant_traits {
361+
VariantTraitMode::Repr => generate_variant_impls(
362+
w,
363+
env,
364+
config,
365+
&flags.name,
366+
version,
367+
flags.deprecated_version,
368+
"u",
369+
"Some(Self::from_bits(variant.get::<u32>()?)?)",
370+
"self.into_glib().to_variant()",
371+
)?,
372+
VariantTraitMode::String => {
373+
let flagsclass = use_glib_type(env, "FlagsClass");
374+
generate_variant_impls(
375+
w,
376+
env,
377+
config,
378+
&flags.name,
379+
version,
380+
flags.deprecated_version,
381+
"s",
382+
&format!(
383+
"if !variant.is::<String>() {{
384+
return None;
385+
}}
386+
let flags_class = {flagsclass}::new(<Self as StaticType>::static_type()).unwrap();
387+
Self::from_bits(flags_class.from_nick_string(variant.str()?).ok()?)",
388+
),
389+
&format!(
390+
"let flags_class = {flagsclass}::new(<Self as StaticType>::static_type()).unwrap();
391+
flags_class.to_nick_string(self.into_glib()).to_variant()",
392+
)
393+
)?
394+
}
395+
_ => {}
396+
}
397+
360398
Ok(())
361399
}

src/codegen/mod.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
env::Env,
1212
file_saver::*,
1313
library::Member,
14+
nameutil::use_glib_type,
1415
version::Version,
1516
};
1617

@@ -43,6 +44,8 @@ mod trampoline;
4344
mod trampoline_from_glib;
4445
mod visibility;
4546
pub use visibility::Visibility;
47+
48+
use self::general::{allow_deprecated, cfg_condition_no_doc};
4649
mod trampoline_to_glib;
4750
pub mod translate_from_glib;
4851
pub mod translate_to_glib;
@@ -168,3 +171,82 @@ pub fn generate_default_impl<
168171
Ok(())
169172
}
170173
}
174+
175+
pub fn generate_variant_impls(
176+
w: &mut dyn Write,
177+
env: &Env,
178+
config: &GObject,
179+
type_name: &str,
180+
type_version: Option<Version>,
181+
deprecated_version: Option<Version>,
182+
static_variant_type_str: &str,
183+
from_variant_impl: &str,
184+
to_variant_impl: &str,
185+
) -> Result<()> {
186+
let assert = if env.config.generate_safety_asserts {
187+
"skip_assert_initialized!();\n\t\t"
188+
} else {
189+
""
190+
};
191+
let gvariant = use_glib_type(env, "Variant");
192+
let tovariant = use_glib_type(env, "ToVariant");
193+
194+
version_condition(w, env, None, type_version, false, 0)?;
195+
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
196+
allow_deprecated(w, deprecated_version, false, 0)?;
197+
writeln!(
198+
w,
199+
"impl {staticvarianttype} for {type_name} {{
200+
fn static_variant_type() -> std::borrow::Cow<'static, {variantty}> {{
201+
{assert}std::borrow::Cow::Borrowed(unsafe {{
202+
{variantty}::from_str_unchecked(\"{static_variant_type_str}\")
203+
}})
204+
}}
205+
}}",
206+
staticvarianttype = use_glib_type(env, "StaticVariantType"),
207+
variantty = use_glib_type(env, "VariantTy"),
208+
)?;
209+
writeln!(w)?;
210+
211+
version_condition(w, env, None, type_version, false, 0)?;
212+
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
213+
allow_deprecated(w, deprecated_version, false, 0)?;
214+
writeln!(
215+
w,
216+
"impl {fromvariant} for {type_name} {{
217+
fn from_variant(variant: &{gvariant}) -> Option<Self> {{
218+
{assert}{from_variant_impl}
219+
}}
220+
}}",
221+
fromvariant = use_glib_type(env, "FromVariant"),
222+
)?;
223+
writeln!(w)?;
224+
225+
version_condition(w, env, None, type_version, false, 0)?;
226+
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
227+
allow_deprecated(w, deprecated_version, false, 0)?;
228+
writeln!(
229+
w,
230+
"impl {tovariant} for {type_name} {{
231+
fn to_variant(&self) -> {gvariant} {{
232+
{assert}{to_variant_impl}
233+
}}
234+
}}"
235+
)?;
236+
writeln!(w)?;
237+
238+
version_condition(w, env, None, type_version, false, 0)?;
239+
cfg_condition_no_doc(w, config.cfg_condition.as_ref(), false, 0)?;
240+
allow_deprecated(w, deprecated_version, false, 0)?;
241+
writeln!(
242+
w,
243+
"impl From<{type_name}> for {gvariant} {{
244+
fn from(v: {type_name}) -> Self {{
245+
{assert}{tovariant}::to_variant(&v)
246+
}}
247+
}}",
248+
)?;
249+
writeln!(w)?;
250+
251+
Ok(())
252+
}

src/config/config.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,38 @@ impl GirVersion {
9090
}
9191
}
9292

93+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
94+
pub enum VariantTraitMode {
95+
#[default]
96+
None,
97+
Repr,
98+
String,
99+
}
100+
101+
impl VariantTraitMode {
102+
pub fn is_none(self) -> bool {
103+
self == Self::None
104+
}
105+
pub fn is_repr(self) -> bool {
106+
self == Self::Repr
107+
}
108+
pub fn is_string(self) -> bool {
109+
self == Self::String
110+
}
111+
}
112+
113+
impl FromStr for VariantTraitMode {
114+
type Err = String;
115+
fn from_str(s: &str) -> Result<Self, Self::Err> {
116+
match s {
117+
"none" => Ok(Self::None),
118+
"repr" => Ok(Self::Repr),
119+
"string" => Ok(Self::String),
120+
e => Err(format!("Wrong variant trait mode: \"{}\"", e)),
121+
}
122+
}
123+
}
124+
93125
#[derive(Debug)]
94126
pub struct Config {
95127
pub work_mode: WorkMode,
@@ -113,6 +145,7 @@ pub struct Config {
113145
pub concurrency: library::Concurrency,
114146
pub single_version_file: Option<PathBuf>,
115147
pub generate_display_trait: bool,
148+
pub generate_variant_traits: VariantTraitMode,
116149
pub trust_return_value_nullability: bool,
117150
pub docs_rs_features: Vec<String>,
118151
pub disable_format: bool,
@@ -255,6 +288,13 @@ impl Config {
255288
None => true,
256289
};
257290

291+
let generate_variant_traits = match toml.lookup("options.generate_variant_traits") {
292+
Some(v) => v
293+
.as_result_str("options.generate_variant_traits")?
294+
.parse()?,
295+
None => Default::default(),
296+
};
297+
258298
let trust_return_value_nullability =
259299
match toml.lookup("options.trust_return_value_nullability") {
260300
Some(v) => v.as_result_bool("options.trust_return_value_nullability")?,
@@ -281,6 +321,7 @@ impl Config {
281321
t,
282322
concurrency,
283323
generate_display_trait,
324+
generate_variant_traits,
284325
generate_builder,
285326
trust_return_value_nullability,
286327
)
@@ -291,6 +332,7 @@ impl Config {
291332
&toml,
292333
concurrency,
293334
generate_display_trait,
335+
generate_variant_traits,
294336
generate_builder,
295337
trust_return_value_nullability,
296338
);
@@ -367,6 +409,7 @@ impl Config {
367409
concurrency,
368410
single_version_file,
369411
generate_display_trait,
412+
generate_variant_traits,
370413
trust_return_value_nullability,
371414
docs_rs_features,
372415
disable_format,

0 commit comments

Comments
 (0)