blob: 6b7e58011a5ab4fcf92b2a0263a160be8e067e74 [file] [log] [blame]
David Tolnay2f3e90b2020-10-31 22:16:51 -07001use crate::gen::out::{Content, OutFile};
David Tolnay353d98c2020-10-28 15:43:35 -07002use crate::syntax::{self, IncludeKind};
David Tolnay8810a542020-10-31 21:39:22 -07003use std::ops::{Deref, DerefMut};
David Tolnay9c68b1a2020-03-06 11:12:55 -08004
David Tolnay0e01d642020-10-16 12:54:44 -07005/// The complete contents of the "rust/cxx.h" header.
David Tolnay736cbca2020-03-11 16:49:18 -07006pub static HEADER: &str = include_str!("include/cxx.h");
David Tolnay7db73692019-10-20 14:51:12 -04007
David Tolnay700cd0c2020-10-28 12:40:27 -07008/// 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)]
David Tolnay4aae7c02020-10-28 12:35:42 -070013pub struct Include {
David Tolnay700cd0c2020-10-28 12:40:27 -070014 /// The header's path, not including the enclosing quotation marks or angle
15 /// brackets.
David Tolnay4aae7c02020-10-28 12:35:42 -070016 pub path: String,
David Tolnay700cd0c2020-10-28 12:40:27 -070017 /// Whether to emit `#include "path"` or `#include <path>`.
David Tolnay4aae7c02020-10-28 12:35:42 -070018 pub kind: IncludeKind,
19}
20
David Tolnay3577d452020-03-17 21:48:13 -070021#[derive(Default, PartialEq)]
David Tolnay97c5b862020-11-01 14:59:01 -080022pub struct Includes<'a> {
David Tolnay12af7e42020-10-31 21:09:23 -070023 pub custom: Vec<Include>,
David Tolnayf799b372020-11-29 23:57:42 -080024 pub algorithm: bool,
David Tolnayb7a7cb62020-03-17 21:18:40 -070025 pub array: bool,
David Tolnay30430f12020-03-19 20:49:00 -070026 pub cstddef: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080027 pub cstdint: bool,
David Tolnayebef4a22020-03-17 15:33:47 -070028 pub cstring: bool,
David Tolnayb7a7cb62020-03-17 21:18:40 -070029 pub exception: bool,
David Tolnay08a03db2020-12-09 23:04:36 -080030 pub functional: bool,
David Tolnayf799b372020-11-29 23:57:42 -080031 pub initializer_list: bool,
David Tolnayd1df4c72020-11-25 20:38:05 -080032 pub iterator: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080033 pub memory: bool,
David Tolnay0ecd05a2020-07-29 16:32:03 -070034 pub new: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080035 pub string: bool,
36 pub type_traits: bool,
David Tolnay4791f1c2020-03-17 21:53:16 -070037 pub utility: bool,
David Tolnay8b7f8992020-04-25 13:06:08 -070038 pub vector: bool,
David Tolnayda38b7c2020-09-16 11:50:04 -040039 pub basetsd: bool,
David Tolnay74dd66f2020-12-12 22:03:47 -080040 pub sys_types: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080041 pub content: Content<'a>,
David Tolnay9c68b1a2020-03-06 11:12:55 -080042}
43
David Tolnay97c5b862020-11-01 14:59:01 -080044impl<'a> Includes<'a> {
David Tolnay9c68b1a2020-03-06 11:12:55 -080045 pub fn new() -> Self {
46 Includes::default()
47 }
48
David Tolnay353d98c2020-10-28 15:43:35 -070049 pub fn insert(&mut self, include: impl Into<Include>) {
50 self.custom.push(include.into());
David Tolnay9c68b1a2020-03-06 11:12:55 -080051 }
52}
53
David Tolnay2f3e90b2020-10-31 22:16:51 -070054pub(super) fn write(out: &mut OutFile) {
David Tolnay58711a92020-11-01 19:11:37 -080055 let header = out.header;
David Tolnay2f3e90b2020-10-31 22:16:51 -070056 let include = &mut out.include;
57 let out = &mut include.content;
58
David Tolnay58711a92020-11-01 19:11:37 -080059 if header {
60 writeln!(out, "#pragma once");
61 }
62
David Tolnay2f3e90b2020-10-31 22:16:51 -070063 for include in &include.custom {
64 match include.kind {
65 IncludeKind::Quoted => {
66 writeln!(out, "#include \"{}\"", include.path.escape_default());
67 }
68 IncludeKind::Bracketed => {
69 writeln!(out, "#include <{}>", include.path);
70 }
71 }
72 }
73
David Tolnaya829be62020-11-25 20:41:12 -080074 let Includes {
75 custom: _,
David Tolnayf799b372020-11-29 23:57:42 -080076 algorithm,
David Tolnaya829be62020-11-25 20:41:12 -080077 array,
78 cstddef,
79 cstdint,
80 cstring,
81 exception,
David Tolnay08a03db2020-12-09 23:04:36 -080082 functional,
David Tolnayf799b372020-11-29 23:57:42 -080083 initializer_list,
David Tolnaya829be62020-11-25 20:41:12 -080084 iterator,
85 memory,
86 new,
87 string,
88 type_traits,
89 utility,
90 vector,
91 basetsd,
David Tolnay74dd66f2020-12-12 22:03:47 -080092 sys_types,
David Tolnaya829be62020-11-25 20:41:12 -080093 content: _,
94 } = *include;
95
David Tolnayf799b372020-11-29 23:57:42 -080096 if algorithm {
97 writeln!(out, "#include <algorithm>");
98 }
David Tolnaya829be62020-11-25 20:41:12 -080099 if array {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700100 writeln!(out, "#include <array>");
101 }
David Tolnaya829be62020-11-25 20:41:12 -0800102 if cstddef {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700103 writeln!(out, "#include <cstddef>");
104 }
David Tolnaya829be62020-11-25 20:41:12 -0800105 if cstdint {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700106 writeln!(out, "#include <cstdint>");
107 }
David Tolnaya829be62020-11-25 20:41:12 -0800108 if cstring {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700109 writeln!(out, "#include <cstring>");
110 }
David Tolnaya829be62020-11-25 20:41:12 -0800111 if exception {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700112 writeln!(out, "#include <exception>");
113 }
David Tolnay08a03db2020-12-09 23:04:36 -0800114 if functional {
115 writeln!(out, "#include <functional>");
116 }
David Tolnayf799b372020-11-29 23:57:42 -0800117 if initializer_list {
118 writeln!(out, "#include <initializer_list>");
119 }
David Tolnaya829be62020-11-25 20:41:12 -0800120 if iterator {
David Tolnayd1df4c72020-11-25 20:38:05 -0800121 writeln!(out, "#include <iterator>");
122 }
David Tolnaya829be62020-11-25 20:41:12 -0800123 if memory {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700124 writeln!(out, "#include <memory>");
125 }
David Tolnaya829be62020-11-25 20:41:12 -0800126 if new {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700127 writeln!(out, "#include <new>");
128 }
David Tolnaya829be62020-11-25 20:41:12 -0800129 if string {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700130 writeln!(out, "#include <string>");
131 }
David Tolnaya829be62020-11-25 20:41:12 -0800132 if type_traits {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700133 writeln!(out, "#include <type_traits>");
134 }
David Tolnaya829be62020-11-25 20:41:12 -0800135 if utility {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700136 writeln!(out, "#include <utility>");
137 }
David Tolnaya829be62020-11-25 20:41:12 -0800138 if vector {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700139 writeln!(out, "#include <vector>");
140 }
David Tolnaya829be62020-11-25 20:41:12 -0800141 if basetsd {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700142 writeln!(out, "#if defined(_WIN32)");
143 writeln!(out, "#include <basetsd.h>");
David Tolnay74dd66f2020-12-12 22:03:47 -0800144 }
145 if sys_types {
146 if basetsd {
147 writeln!(out, "#else");
148 } else {
149 writeln!(out, "#if not defined(_WIN32)");
150 }
151 }
152 if sys_types {
153 writeln!(out, "#include <sys/types.h>");
154 }
155 if basetsd || sys_types {
David Tolnay2f3e90b2020-10-31 22:16:51 -0700156 writeln!(out, "#endif");
157 }
158}
159
David Tolnay97c5b862020-11-01 14:59:01 -0800160impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
161 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
David Tolnay700cd0c2020-10-28 12:40:27 -0700162 self.custom.extend(iter.into_iter().cloned());
David Tolnay33d30292020-03-18 18:02:02 -0700163 }
164}
165
David Tolnay97c5b862020-11-01 14:59:01 -0800166impl<'i> From<&'i syntax::Include> for Include {
David Tolnay353d98c2020-10-28 15:43:35 -0700167 fn from(include: &syntax::Include) -> Self {
168 Include {
169 path: include.path.clone(),
170 kind: include.kind,
171 }
172 }
173}
David Tolnay8810a542020-10-31 21:39:22 -0700174
David Tolnay97c5b862020-11-01 14:59:01 -0800175impl<'a> Deref for Includes<'a> {
176 type Target = Content<'a>;
David Tolnay8810a542020-10-31 21:39:22 -0700177
178 fn deref(&self) -> &Self::Target {
179 &self.content
180 }
181}
182
David Tolnay97c5b862020-11-01 14:59:01 -0800183impl<'a> DerefMut for Includes<'a> {
David Tolnay8810a542020-10-31 21:39:22 -0700184 fn deref_mut(&mut self) -> &mut Self::Target {
185 &mut self.content
186 }
187}