1 use crate::gen::out::{Content, OutFile};
2 use crate::syntax::{self, IncludeKind};
3 use std::ops::{Deref, DerefMut};
4
5 /// The complete contents of the "rust/cxx.h" header.
6 pub static HEADER: &str = include_str!("include/cxx.h");
7
8 /// A header to #include.
9 ///
10 /// The cxxbridge tool does not parse or even require the given paths to exist;
11 /// they simply go into the generated C++ code as #include lines.
12 #[derive(Clone, PartialEq, Debug)]
13 pub struct Include {
14 /// The header's path, not including the enclosing quotation marks or angle
15 /// brackets.
16 pub path: String,
17 /// Whether to emit `#include "path"` or `#include <path>`.
18 pub kind: IncludeKind,
19 }
20
21 #[derive(Default, PartialEq)]
22 pub 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 stdexcept: bool,
37 pub string: bool,
38 pub type_traits: bool,
39 pub utility: bool,
40 pub vector: bool,
41 pub basetsd: bool,
42 pub sys_types: bool,
43 pub content: Content<'a>,
44 }
45
46 impl<'a> Includes<'a> {
new() -> Self47 pub fn new() -> Self {
48 Includes::default()
49 }
50
insert(&mut self, include: impl Into<Include>)51 pub fn insert(&mut self, include: impl Into<Include>) {
52 self.custom.push(include.into());
53 }
54
has_cxx_header(&self) -> bool55 pub fn has_cxx_header(&self) -> bool {
56 self.custom
57 .iter()
58 .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
59 }
60 }
61
write(out: &mut OutFile)62 pub(super) fn write(out: &mut OutFile) {
63 let header = out.header;
64 let include = &mut out.include;
65 let cxx_header = include.has_cxx_header();
66 let out = &mut include.content;
67
68 if header {
69 writeln!(out, "#pragma once");
70 }
71
72 for include in &include.custom {
73 match include.kind {
74 IncludeKind::Quoted => {
75 writeln!(out, "#include \"{}\"", include.path.escape_default());
76 }
77 IncludeKind::Bracketed => {
78 writeln!(out, "#include <{}>", include.path);
79 }
80 }
81 }
82
83 let Includes {
84 custom: _,
85 algorithm,
86 array,
87 cassert,
88 cstddef,
89 cstdint,
90 cstring,
91 exception,
92 functional,
93 initializer_list,
94 iterator,
95 memory,
96 new,
97 stdexcept,
98 string,
99 type_traits,
100 utility,
101 vector,
102 basetsd,
103 sys_types,
104 content: _,
105 } = *include;
106
107 if algorithm && !cxx_header {
108 writeln!(out, "#include <algorithm>");
109 }
110 if array && !cxx_header {
111 writeln!(out, "#include <array>");
112 }
113 if cassert && !cxx_header {
114 writeln!(out, "#include <cassert>");
115 }
116 if cstddef && !cxx_header {
117 writeln!(out, "#include <cstddef>");
118 }
119 if cstdint && !cxx_header {
120 writeln!(out, "#include <cstdint>");
121 }
122 if cstring {
123 writeln!(out, "#include <cstring>");
124 }
125 if exception && !cxx_header {
126 writeln!(out, "#include <exception>");
127 }
128 if functional {
129 writeln!(out, "#include <functional>");
130 }
131 if initializer_list && !cxx_header {
132 writeln!(out, "#include <initializer_list>");
133 }
134 if iterator && !cxx_header {
135 writeln!(out, "#include <iterator>");
136 }
137 if memory {
138 writeln!(out, "#include <memory>");
139 }
140 if new && !cxx_header {
141 writeln!(out, "#include <new>");
142 }
143 if stdexcept && !cxx_header {
144 writeln!(out, "#include <stdexcept>");
145 }
146 if string && !cxx_header {
147 writeln!(out, "#include <string>");
148 }
149 if type_traits && !cxx_header {
150 writeln!(out, "#include <type_traits>");
151 }
152 if utility && !cxx_header {
153 writeln!(out, "#include <utility>");
154 }
155 if vector && !cxx_header {
156 writeln!(out, "#include <vector>");
157 }
158 if basetsd && !cxx_header {
159 writeln!(out, "#if defined(_WIN32)");
160 writeln!(out, "#include <basetsd.h>");
161 }
162 if sys_types && !cxx_header {
163 if basetsd {
164 writeln!(out, "#else");
165 } else {
166 writeln!(out, "#if not defined(_WIN32)");
167 }
168 }
169 if sys_types && !cxx_header {
170 writeln!(out, "#include <sys/types.h>");
171 }
172 if (basetsd || sys_types) && !cxx_header {
173 writeln!(out, "#endif");
174 }
175 }
176
177 impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I)178 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
179 self.custom.extend(iter.into_iter().cloned());
180 }
181 }
182
183 impl<'i> From<&'i syntax::Include> for Include {
from(include: &syntax::Include) -> Self184 fn from(include: &syntax::Include) -> Self {
185 Include {
186 path: include.path.clone(),
187 kind: include.kind,
188 }
189 }
190 }
191
192 impl<'a> Deref for Includes<'a> {
193 type Target = Content<'a>;
194
deref(&self) -> &Self::Target195 fn deref(&self) -> &Self::Target {
196 &self.content
197 }
198 }
199
200 impl<'a> DerefMut for Includes<'a> {
deref_mut(&mut self) -> &mut Self::Target201 fn deref_mut(&mut self) -> &mut Self::Target {
202 &mut self.content
203 }
204 }
205