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