1use crate::gen::out::{Content, OutFile};
2use crate::syntax::{self, IncludeKind};
3use std::ops::{Deref, DerefMut};
4
5pub static HEADER: &str = include_str!("include/cxx.h");
7
8#[derive(Clone, PartialEq, Debug)]
13pub struct Include {
14 pub path: String,
17 pub kind: IncludeKind,
19}
20
21#[derive(Default, PartialEq)]
22pub(crate) struct Includes<'a> {
23 pub custom: Vec<Include>,
24 pub algorithm: bool,
25 pub array: bool,
26 pub cassert: bool,
27 pub cstddef: bool,
28 pub cstdint: bool,
29 pub cstring: bool,
30 pub exception: bool,
31 pub functional: bool,
32 pub initializer_list: bool,
33 pub iterator: bool,
34 pub memory: bool,
35 pub new: bool,
36 pub ranges: bool,
37 pub stdexcept: bool,
38 pub string: bool,
39 pub string_view: bool,
40 pub type_traits: bool,
41 pub utility: bool,
42 pub vector: bool,
43 pub basetsd: bool,
44 pub sys_types: bool,
45 pub content: Content<'a>,
46}
47
48impl<'a> Includes<'a> {
49 pub(crate) fn new() -> Self {
50 Includes::default()
51 }
52
53 pub(crate) fn insert(&mut self, include: impl Into<Include>) {
54 self.custom.push(include.into());
55 }
56
57 pub(crate) fn has_cxx_header(&self) -> bool {
58 self.custom
59 .iter()
60 .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
61 }
62}
63
64pub(super) fn write(out: &mut OutFile) {
65 let header = out.header;
66 let include = &mut out.include;
67 let cxx_header = include.has_cxx_header();
68 let out = &mut include.content;
69
70 if header {
71 writeln!(out, "#pragma once");
72 }
73
74 for include in &include.custom {
75 match include.kind {
76 IncludeKind::Quoted => {
77 writeln!(out, "#include \"{}\"", include.path.escape_default());
78 }
79 IncludeKind::Bracketed => {
80 writeln!(out, "#include <{}>", include.path);
81 }
82 }
83 }
84
85 let Includes {
86 custom: _,
87 algorithm,
88 array,
89 cassert,
90 cstddef,
91 cstdint,
92 cstring,
93 exception,
94 functional,
95 initializer_list,
96 iterator,
97 memory,
98 new,
99 ranges,
100 stdexcept,
101 string,
102 string_view,
103 type_traits,
104 utility,
105 vector,
106 basetsd,
107 sys_types,
108 content: _,
109 } = *include;
110
111 if algorithm && !cxx_header {
112 writeln!(out, "#include <algorithm>");
113 }
114 if array && !cxx_header {
115 writeln!(out, "#include <array>");
116 }
117 if cassert && !cxx_header {
118 writeln!(out, "#include <cassert>");
119 }
120 if cstddef && !cxx_header {
121 writeln!(out, "#include <cstddef>");
122 }
123 if cstdint && !cxx_header {
124 writeln!(out, "#include <cstdint>");
125 }
126 if cstring {
127 writeln!(out, "#include <cstring>");
128 }
129 if exception && !cxx_header {
130 writeln!(out, "#include <exception>");
131 }
132 if functional {
133 writeln!(out, "#include <functional>");
134 }
135 if initializer_list && !cxx_header {
136 writeln!(out, "#include <initializer_list>");
137 }
138 if iterator && !cxx_header {
139 writeln!(out, "#include <iterator>");
140 }
141 if memory {
142 writeln!(out, "#include <memory>");
143 }
144 if new && !cxx_header {
145 writeln!(out, "#include <new>");
146 }
147 if stdexcept && !cxx_header {
148 writeln!(out, "#include <stdexcept>");
149 }
150 if string && !cxx_header {
151 writeln!(out, "#include <string>");
152 }
153 if type_traits && !cxx_header {
154 writeln!(out, "#include <type_traits>");
155 }
156 if utility && !cxx_header {
157 writeln!(out, "#include <utility>");
158 }
159 if vector && !cxx_header {
160 writeln!(out, "#include <vector>");
161 }
162 if basetsd && !cxx_header {
163 writeln!(out, "#if defined(_WIN32)");
164 writeln!(out, "#include <basetsd.h>");
165 }
166 if sys_types && !cxx_header {
167 if basetsd {
168 writeln!(out, "#else");
169 } else {
170 writeln!(out, "#if not defined(_WIN32)");
171 }
172 }
173 if sys_types && !cxx_header {
174 writeln!(out, "#include <sys/types.h>");
175 }
176 if (basetsd || sys_types) && !cxx_header {
177 writeln!(out, "#endif");
178 }
179 if string_view && !cxx_header {
180 writeln!(out, "#if __cplusplus >= 201703L");
181 writeln!(out, "#include <string_view>");
182 writeln!(out, "#endif");
183 }
184 if ranges && !cxx_header {
185 writeln!(out, "#if __cplusplus >= 202002L");
186 writeln!(out, "#include <ranges>");
187 writeln!(out, "#endif");
188 }
189}
190
191impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
192 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
193 self.custom.extend(iter.into_iter().cloned());
194 }
195}
196
197impl From<&syntax::Include> for Include {
198 fn from(include: &syntax::Include) -> Self {
199 Include {
200 path: include.path.clone(),
201 kind: include.kind,
202 }
203 }
204}
205
206impl<'a> Deref for Includes<'a> {
207 type Target = Content<'a>;
208
209 fn deref(&self) -> &Self::Target {
210 &self.content
211 }
212}
213
214impl<'a> DerefMut for Includes<'a> {
215 fn deref_mut(&mut self) -> &mut Self::Target {
216 &mut self.content
217 }
218}