1use std::io::{Result, Write};
2
3use super::{function, general, trait_impls};
4use crate::{
5 analysis::{self, record_type::RecordType, special_functions::Type},
6 env::Env,
7 library,
8 traits::MaybeRef,
9};
10
11pub fn generate(w: &mut dyn Write, env: &Env, analysis: &analysis::record::Info) -> Result<()> {
12 let type_ = analysis.type_(&env.library);
13
14 general::start_comments(w, &env.config)?;
15 general::uses(w, env, &analysis.imports, type_.version)?;
16
17 if RecordType::of(env.type_(analysis.type_id).maybe_ref().unwrap()) == RecordType::AutoBoxed {
18 if let Some((ref glib_get_type, _)) = analysis.glib_get_type {
19 general::define_auto_boxed_type(
20 w,
21 env,
22 &analysis.name,
23 &type_.c_type,
24 analysis.boxed_inline,
25 &analysis.init_function_expression,
26 &analysis.copy_into_function_expression,
27 &analysis.clear_function_expression,
28 glib_get_type,
29 &analysis.derives,
30 analysis.visibility,
31 analysis.type_id,
32 )?;
33 } else {
34 panic!(
35 "Record {} has record_boxed=true but don't have glib:get_type function",
36 analysis.name
37 );
38 }
39 } else if let (Some(ref_fn), Some(unref_fn)) = (
40 analysis.specials.traits().get(&Type::Ref),
41 analysis.specials.traits().get(&Type::Unref),
42 ) {
43 general::define_shared_type(
44 w,
45 env,
46 &analysis.name,
47 &type_.c_type,
48 &ref_fn.glib_name,
49 &unref_fn.glib_name,
50 analysis.glib_get_type.as_ref().map(|(f, v)| {
51 if v > &analysis.version {
52 (f.clone(), *v)
53 } else {
54 (f.clone(), None)
55 }
56 }),
57 &analysis.derives,
58 analysis.visibility,
59 analysis.type_id,
60 )?;
61 } else if let (Some(copy_fn), Some(free_fn)) = (
62 analysis.specials.traits().get(&Type::Copy),
63 analysis.specials.traits().get(&Type::Free),
64 ) {
65 general::define_boxed_type(
66 w,
67 env,
68 &analysis.name,
69 &type_.c_type,
70 copy_fn,
71 &free_fn.glib_name,
72 analysis.boxed_inline,
73 &analysis.init_function_expression,
74 &analysis.copy_into_function_expression,
75 &analysis.clear_function_expression,
76 analysis.glib_get_type.as_ref().map(|(f, v)| {
77 if v > &analysis.version {
78 (f.clone(), *v)
79 } else {
80 (f.clone(), None)
81 }
82 }),
83 &analysis.derives,
84 analysis.visibility,
85 analysis.type_id,
86 )?;
87 } else {
88 panic!(
89 "Missing memory management functions for {}",
90 analysis.full_name
91 );
92 }
93
94 if analysis
95 .functions
96 .iter()
97 .any(|f| f.status.need_generate() && !f.hidden)
98 {
99 writeln!(w)?;
100 write!(w, "impl {} {{", analysis.name)?;
101
102 for func_analysis in &analysis.functions {
103 function::generate(
104 w,
105 env,
106 Some(analysis.type_id),
107 func_analysis,
108 Some(&analysis.specials),
109 analysis.version,
110 false,
111 false,
112 1,
113 )?;
114 }
115
116 writeln!(w, "}}")?;
117 }
118
119 general::declare_default_from_new(w, env, &analysis.name, &analysis.functions, false)?;
120
121 trait_impls::generate(
122 w,
123 env,
124 &analysis.name,
125 &analysis.functions,
126 &analysis.specials,
127 None,
128 analysis.version,
129 None, )?;
131
132 if analysis.concurrency != library::Concurrency::None {
133 writeln!(w)?;
134 }
135
136 match analysis.concurrency {
137 library::Concurrency::Send | library::Concurrency::SendSync => {
138 writeln!(w, "unsafe impl Send for {} {{}}", analysis.name)?;
139 }
140 _ => (),
141 }
142
143 if analysis.concurrency == library::Concurrency::SendSync {
144 writeln!(w, "unsafe impl Sync for {} {{}}", analysis.name)?;
145 }
146
147 Ok(())
148}
149
150pub fn generate_reexports(
151 env: &Env,
152 analysis: &analysis::record::Info,
153 module_name: &str,
154 contents: &mut Vec<String>,
155) {
156 let cfg_condition = general::cfg_condition_string(analysis.cfg_condition.as_ref(), false, 0);
157 let version_cfg = general::version_condition_string(
158 env,
159 Some(analysis.type_id.ns_id),
160 analysis.version,
161 false,
162 0,
163 );
164 let mut cfg = String::new();
165 if let Some(s) = cfg_condition {
166 cfg.push_str(&s);
167 cfg.push('\n');
168 };
169 if let Some(s) = version_cfg {
170 cfg.push_str(&s);
171 cfg.push('\n');
172 };
173 contents.push(String::new());
174 contents.push(format!("{cfg}mod {module_name};"));
175 contents.push(format!(
176 "{}{} use self::{}::{};",
177 cfg,
178 analysis.visibility.export_visibility(),
179 module_name,
180 analysis.name
181 ));
182}