1use crate::{
2 analysis::{
3 self, conversion_type::ConversionType, rust_type::RustType, try_from_glib::TryFromGlib,
4 },
5 chunk::conversion_from_glib::Mode,
6 env::Env,
7 library,
8 nameutil::use_glib_type,
9 traits::*,
10};
11
12pub trait TranslateFromGlib {
13 fn translate_from_glib_as_function(
14 &self,
15 env: &Env,
16 array_length: Option<&str>,
17 ) -> (String, String);
18}
19
20impl TranslateFromGlib for Mode {
21 fn translate_from_glib_as_function(
22 &self,
23 env: &Env,
24 array_length: Option<&str>,
25 ) -> (String, String) {
26 use crate::analysis::conversion_type::ConversionType::*;
27 match ConversionType::of(env, self.typ) {
28 Direct => (String::new(), String::new()),
29 Scalar => match env.library.type_(self.typ) {
30 library::Type::Basic(library::Basic::UniChar) => (
31 "std::convert::TryFrom::try_from(".into(),
32 ").expect(\"conversion from an invalid Unicode value attempted\")".into(),
33 ),
34 _ => ("from_glib(".into(), ")".into()),
35 },
36 Option => {
37 let (pre, post) = match &self.try_from_glib {
38 TryFromGlib::Option => ("from_glib(", ")"),
39 TryFromGlib::OptionMandatory => (
40 "try_from_glib(",
41 ").expect(\"mandatory glib value is None\")",
42 ),
43 other => panic!("Unexpected {other:?} for ConversionType::Option"),
44 };
45 (pre.to_string(), post.to_string())
46 }
47 Result { .. } => {
48 let (pre, post) = match &self.try_from_glib {
49 TryFromGlib::Result { .. } => ("try_from_glib(", ")"),
50 TryFromGlib::ResultInfallible { .. } => (
51 "try_from_glib(",
52 ").unwrap_or_else(|err| panic!(\"infallible {}\", err))",
53 ),
54 other => panic!("Unexpected {other:?} for ConversionType::Result"),
55 };
56 (pre.to_string(), post.to_string())
57 }
58 Pointer => {
59 let trans = from_glib_xxx(self.transfer, array_length);
60 match env.type_(self.typ) {
61 library::Type::List(..)
62 | library::Type::SList(..)
63 | library::Type::PtrArray(..)
64 | library::Type::CArray(..) => {
65 if array_length.is_some() {
66 (format!("FromGlibContainer::{}", trans.0), trans.1)
67 } else {
68 (format!("FromGlibPtrContainer::{}", trans.0), trans.1)
69 }
70 }
71 _ => trans,
72 }
73 }
74 Borrow => ("/*TODO: conversion Borrow*/".into(), String::new()),
75 Unknown => ("/*Unknown conversion*/".into(), String::new()),
76 }
77 }
78}
79
80impl TranslateFromGlib for analysis::return_value::Info {
81 fn translate_from_glib_as_function(
82 &self,
83 env: &Env,
84 array_length: Option<&str>,
85 ) -> (String, String) {
86 match self.parameter {
87 Some(ref par) => match self.base_tid {
88 Some(tid) => {
89 let rust_type = RustType::builder(env, tid)
90 .direction(par.lib_par.direction)
91 .try_from_glib(&par.try_from_glib)
92 .try_build();
93 let from_glib_xxx = from_glib_xxx(par.lib_par.transfer, None);
94
95 let prefix = if *par.lib_par.nullable {
96 format!("Option::<{}>::{}", rust_type.into_string(), from_glib_xxx.0)
97 } else {
98 format!("{}::{}", rust_type.into_string(), from_glib_xxx.0)
99 };
100 let suffix_function = if *par.lib_par.nullable {
101 "map(|o| o.unsafe_cast())"
102 } else {
103 "unsafe_cast()"
104 };
105
106 if let Some(ref msg) = self.nullable_return_is_error {
107 assert!(*par.lib_par.nullable);
108 (
109 prefix,
110 format!(
111 "{}.{}.ok_or_else(|| {}(\"{}\"))",
112 from_glib_xxx.1,
113 suffix_function,
114 use_glib_type(env, "bool_error!"),
115 msg
116 ),
117 )
118 } else {
119 (prefix, format!("{}.{}", from_glib_xxx.1, suffix_function))
120 }
121 }
122 None if self.bool_return_is_error.is_some() => (
123 use_glib_type(env, "result_from_gboolean!("),
124 format!(", \"{}\")", self.bool_return_is_error.as_ref().unwrap()),
125 ),
126 None if self.nullable_return_is_error.is_some() => {
127 let res = Mode::from(par).translate_from_glib_as_function(env, array_length);
128 if let Some(ref msg) = self.nullable_return_is_error {
129 assert!(*par.lib_par.nullable);
130 (
131 format!("Option::<_>::{}", res.0),
132 format!(
133 "{}.ok_or_else(|| {}(\"{}\"))",
134 res.1,
135 use_glib_type(env, "bool_error!"),
136 msg
137 ),
138 )
139 } else {
140 res
141 }
142 }
143 None => Mode::from(par).translate_from_glib_as_function(env, array_length),
144 },
145 None => (String::new(), ";".into()),
146 }
147 }
148}
149
150fn from_glib_xxx(transfer: library::Transfer, array_length: Option<&str>) -> (String, String) {
151 use crate::library::Transfer;
152 let good_print = |name: &str| format!(", {name}.assume_init() as _)");
153 match (transfer, array_length) {
154 (Transfer::None, None) => ("from_glib_none(".into(), ")".into()),
155 (Transfer::Full, None) => ("from_glib_full(".into(), ")".into()),
156 (Transfer::Container, None) => ("from_glib_container(".into(), ")".into()),
157 (Transfer::None, Some(array_length_name)) => {
158 ("from_glib_none_num(".into(), good_print(array_length_name))
159 }
160 (Transfer::Full, Some(array_length_name)) => {
161 ("from_glib_full_num(".into(), good_print(array_length_name))
162 }
163 (Transfer::Container, Some(array_length_name)) => (
164 "from_glib_container_num(".into(),
165 good_print(array_length_name),
166 ),
167 }
168}