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