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}