1mod formatter;
2pub(crate) mod gen;
3mod header;
4
5pub use self::formatter::CFormatter;
6pub(crate) use self::formatter::CAPI_NAMESPACE;
7pub use self::gen::ItemGenContext;
8pub(crate) use self::header::Header;
9
10use crate::{ErrorStore, FileMap};
11use diplomat_core::hir::BackendAttrSupport;
12use diplomat_core::hir::{self, DocsUrlGenerator};
13
14pub(crate) fn attr_support() -> BackendAttrSupport {
15 let mut a = BackendAttrSupport::default();
16
17 a.namespacing = false;
18 a.memory_sharing = true;
19 a.non_exhaustive_structs = false;
20 a.method_overloading = false;
21 a.utf8_strings = true;
22 a.utf16_strings = true;
23 a.static_slices = true;
24
25 a.constructors = false;
26 a.named_constructors = false;
27 a.fallible_constructors = false;
28 a.accessors = false;
29 a.static_accessors = false;
30 a.comparators = false;
31 a.stringifiers = false;
32 a.iterators = false;
33 a.iterables = false;
34 a.indexing = false;
35 a.arithmetic = false;
36 a.option = true;
37 a.callbacks = true;
38 a.traits = true;
39 a.custom_errors = false;
40 a.traits_are_send = false;
41 a.traits_are_sync = false;
42 a.generate_mocking_interface = false;
43 a.abi_compatibles = true;
44 a.struct_refs = true;
45 a.free_functions = true;
46
47 a
48}
49
50#[derive(askama::Template)]
51#[template(path = "c/runtime.h.jinja", escape = "none")]
52pub struct Runtime;
53
54pub(crate) fn run<'tcx>(
55 tcx: &'tcx hir::TypeContext,
56 config: &crate::Config,
57 docs_url_gen: &'tcx DocsUrlGenerator,
58) -> (FileMap, ErrorStore<'tcx, String>) {
59 let files = FileMap::default();
60 let formatter = CFormatter::new(tcx, false, config, docs_url_gen);
61 let errors = ErrorStore::default();
62
63 files.add_file("diplomat_runtime.h".into(), Runtime.to_string());
64
65 for (id, ty) in tcx.all_types() {
66 if ty.attrs().disable {
67 continue;
69 }
70
71 let decl_header_path = formatter.fmt_decl_header_path(id.into());
72 let impl_header_path = formatter.fmt_impl_header_path(id.into());
73
74 let _guard = errors.set_context_ty(ty.name().as_str().into());
75 let context = ItemGenContext {
76 tcx,
77 formatter: &formatter,
78 errors: &errors,
79 is_for_cpp: false,
80 decl_header_path: &decl_header_path,
81 impl_header_path: &impl_header_path,
82 };
83
84 let decl_header = match id {
85 hir::TypeId::Enum(e) => context.gen_enum_def(e),
86 hir::TypeId::Opaque(o) => context.gen_opaque_def(o),
87 hir::TypeId::Struct(s) => context.gen_struct_def::<hir::Everywhere>(s),
88 hir::TypeId::OutStruct(s) => context.gen_struct_def::<hir::OutputOnly>(s),
89 _ => unreachable!("unknown AST/HIR variant"),
90 };
91
92 let impl_header = context.gen_impl(id);
93
94 files.add_file(decl_header_path, decl_header.to_string());
95 files.add_file(impl_header_path, impl_header.to_string());
96 }
97
98 for (id, trt) in tcx.all_traits() {
99 if trt.attrs.disable {
100 continue;
102 }
103
104 let decl_header_path = formatter.fmt_decl_header_path(id.into());
105 let impl_header_path = formatter.fmt_impl_header_path(id.into());
106
107 let _guard = errors.set_context_ty(trt.name.as_str().into());
108 let context = ItemGenContext {
109 tcx,
110 formatter: &formatter,
111 errors: &errors,
112 is_for_cpp: false,
113 decl_header_path: &decl_header_path,
114 impl_header_path: &impl_header_path,
115 };
116
117 let decl_header = context.gen_trait_def(id);
118 files.add_file(decl_header_path, decl_header.to_string());
119 }
120 let impl_header_path = "free_functions.h".to_string();
123
124 let context = ItemGenContext {
125 tcx,
126 formatter: &formatter,
127 errors: &errors,
128 is_for_cpp: false,
129 decl_header_path: "",
130 impl_header_path: &impl_header_path,
131 };
132
133 let impl_header = context.gen_function_impls(None, tcx.all_free_functions().map(|(_, m)| m));
134
135 if !impl_header.body.is_empty() {
136 files.add_file(impl_header.path.clone(), impl_header.to_string());
137 }
138
139 (files, errors)
140}