libgir/codegen/
trampoline_from_glib.rs
1use crate::{
2 analysis::{rust_type::RustType, trampoline_parameters::Transformation},
3 env::Env,
4 library,
5 nameutil::is_gstring,
6 traits::*,
7};
8
9pub trait TrampolineFromGlib {
10 fn trampoline_from_glib(&self, env: &Env, need_downcast: bool, nullable: bool) -> String;
11}
12
13impl TrampolineFromGlib for Transformation {
14 fn trampoline_from_glib(&self, env: &Env, need_downcast: bool, nullable: bool) -> String {
15 use crate::analysis::conversion_type::ConversionType::*;
16 let need_type_name = need_downcast || is_need_type_name(env, self.typ);
17 match self.conversion_type {
18 Direct => self.name.clone(),
19 Scalar | Option | Result { .. } => format!("from_glib({})", self.name),
20 Borrow | Pointer => {
21 let is_borrow = self.conversion_type == Borrow;
22 let need_type_name = need_type_name || (is_borrow && nullable);
23 let (mut left, mut right) = from_glib_xxx(self.transfer, is_borrow);
24 let type_name = RustType::try_new(env, self.typ).into_string();
25 if need_type_name {
26 if is_borrow && nullable {
27 left = format!("Option::<{type_name}>::{left}");
28 } else {
29 left = format!("{type_name}::{left}");
30 }
31 }
32
33 if !nullable {
34 left = format!(
35 "{}{}",
36 if need_downcast && is_borrow { "" } else { "&" },
37 left
38 );
39 } else if nullable && is_borrow {
40 if is_gstring(&type_name) {
41 right = format!("{right}.as_ref().as_ref().map(|s| s.as_str())");
42 } else {
43 right = format!("{right}.as_ref().as_ref()");
44 }
45 } else if is_gstring(&type_name) {
46 right = format!("{right}.as_ref().map(|s| s.as_str())");
47 } else {
48 right = format!("{right}.as_ref()");
49 }
50
51 if need_downcast && is_borrow {
52 right = format!("{right}.unsafe_cast_ref()");
53 } else if need_downcast {
54 right = format!("{right}.unsafe_cast()");
55 }
56
57 format!("{}{}{}", left, self.name, right)
58 }
59 Unknown => format!("/*Unknown conversion*/{}", self.name),
60 }
61 }
62}
63
64pub fn from_glib_xxx(transfer: library::Transfer, is_borrow: bool) -> (String, String) {
65 use crate::library::Transfer::*;
66 match transfer {
67 None if is_borrow => ("from_glib_borrow(".into(), ")".into()),
68 None => ("from_glib_none(".into(), ")".into()),
69 Full => ("from_glib_full(".into(), ")".into()),
70 Container => ("from_glib_container(".into(), ")".into()),
71 }
72}
73
74fn is_need_type_name(env: &Env, type_id: library::TypeId) -> bool {
75 if type_id.ns_id == library::INTERNAL_NAMESPACE {
76 use crate::library::{Basic::*, Type::*};
77 matches!(env.type_(type_id), Basic(Utf8 | Filename | OsString))
78 } else {
79 false
80 }
81}