1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use maplit::hashmap;
use once_cell::sync::Lazy;

use crate::{
	CompiledInterpolation,
	GeneratedElement,
	GeneratorEnv,
	StrExt,
	StringExt,
	TypeRef,
};

#[derive(Clone, Debug, PartialEq)]
pub enum DefinitionLocation {
	Module,
	Type,
	Custom(String),
}

#[derive(Debug)]
pub struct ReturnTypeWrapper<'tu, 'g> {
	type_ref: TypeRef<'tu, 'g>,
	gen_env: &'g GeneratorEnv<'tu>,
	definition_location: DefinitionLocation,
}

impl<'tu, 'g> ReturnTypeWrapper<'tu, 'g> {
	pub fn new(type_ref: TypeRef<'tu, 'g>, gen_env: &'g GeneratorEnv<'tu>, definition_location: DefinitionLocation) -> Self {
		Self { type_ref, gen_env, definition_location }
	}
}

impl GeneratedElement for ReturnTypeWrapper<'_, '_> {
	fn element_order(&self) -> u8 {
		10
	}

	fn element_safe_id(&self) -> String {
		let mut name = self.type_ref.cpp_extern_return().into_owned();
		name.cleanup_name();
		let module = match &self.definition_location {
			DefinitionLocation::Module => {
				self.gen_env.module().into()
			},
			DefinitionLocation::Type => {
				self.type_ref.rust_module()
			},
			DefinitionLocation::Custom(module) => {
				module.into()
			}
		};
		format!("{}-{}", module, name)
	}

	fn gen_cpp(&self) -> String {
		// this explicit instantiation is needed for visual studio compiler, without it it produces error:
		// C linkage function cannot return C++ class
		static CPP_TPL: Lazy<CompiledInterpolation> = Lazy::new(
			|| include_str!("../tpl/return_type_wrapper/cpp.tpl.cpp").compile_interpolation()
		);

		CPP_TPL.interpolate(&hashmap! {
			"cpp_full" => self.type_ref.cpp_extern_return(),
		})
	}
}