blob: cf718dab5aaa9f766af39b9fcc28bfcd21fd3c32 [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 Tolnayb7a7cb62020-03-17 21:18:40 -070024 pub array: bool,
David Tolnay30430f12020-03-19 20:49:00 -070025 pub cstddef: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080026 pub cstdint: bool,
David Tolnayebef4a22020-03-17 15:33:47 -070027 pub cstring: bool,
David Tolnayb7a7cb62020-03-17 21:18:40 -070028 pub exception: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080029 pub memory: bool,
David Tolnay0ecd05a2020-07-29 16:32:03 -070030 pub new: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080031 pub string: bool,
32 pub type_traits: bool,
David Tolnay4791f1c2020-03-17 21:53:16 -070033 pub utility: bool,
David Tolnay8b7f8992020-04-25 13:06:08 -070034 pub vector: bool,
David Tolnayda38b7c2020-09-16 11:50:04 -040035 pub basetsd: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080036 pub content: Content<'a>,
David Tolnay9c68b1a2020-03-06 11:12:55 -080037}
38
David Tolnay97c5b862020-11-01 14:59:01 -080039impl<'a> Includes<'a> {
David Tolnay9c68b1a2020-03-06 11:12:55 -080040 pub fn new() -> Self {
41 Includes::default()
42 }
43
David Tolnay353d98c2020-10-28 15:43:35 -070044 pub fn insert(&mut self, include: impl Into<Include>) {
45 self.custom.push(include.into());
David Tolnay9c68b1a2020-03-06 11:12:55 -080046 }
47}
48
David Tolnay2f3e90b2020-10-31 22:16:51 -070049pub(super) fn write(out: &mut OutFile) {
David Tolnay58711a92020-11-01 19:11:37 -080050 let header = out.header;
David Tolnay2f3e90b2020-10-31 22:16:51 -070051 let include = &mut out.include;
52 let out = &mut include.content;
53
David Tolnay58711a92020-11-01 19:11:37 -080054 if header {
55 writeln!(out, "#pragma once");
56 }
57
David Tolnay2f3e90b2020-10-31 22:16:51 -070058 for include in &include.custom {
59 match include.kind {
60 IncludeKind::Quoted => {
61 writeln!(out, "#include \"{}\"", include.path.escape_default());
62 }
63 IncludeKind::Bracketed => {
64 writeln!(out, "#include <{}>", include.path);
65 }
66 }
67 }
68
69 if include.array {
70 writeln!(out, "#include <array>");
71 }
72 if include.cstddef {
73 writeln!(out, "#include <cstddef>");
74 }
75 if include.cstdint {
76 writeln!(out, "#include <cstdint>");
77 }
78 if include.cstring {
79 writeln!(out, "#include <cstring>");
80 }
81 if include.exception {
82 writeln!(out, "#include <exception>");
83 }
84 if include.memory {
85 writeln!(out, "#include <memory>");
86 }
87 if include.new {
88 writeln!(out, "#include <new>");
89 }
90 if include.string {
91 writeln!(out, "#include <string>");
92 }
93 if include.type_traits {
94 writeln!(out, "#include <type_traits>");
95 }
96 if include.utility {
97 writeln!(out, "#include <utility>");
98 }
99 if include.vector {
100 writeln!(out, "#include <vector>");
101 }
102 if include.basetsd {
103 writeln!(out, "#if defined(_WIN32)");
104 writeln!(out, "#include <basetsd.h>");
105 writeln!(out, "#endif");
106 }
107}
108
David Tolnay97c5b862020-11-01 14:59:01 -0800109impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
110 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
David Tolnay700cd0c2020-10-28 12:40:27 -0700111 self.custom.extend(iter.into_iter().cloned());
David Tolnay33d30292020-03-18 18:02:02 -0700112 }
113}
114
David Tolnay97c5b862020-11-01 14:59:01 -0800115impl<'i> From<&'i syntax::Include> for Include {
David Tolnay353d98c2020-10-28 15:43:35 -0700116 fn from(include: &syntax::Include) -> Self {
117 Include {
118 path: include.path.clone(),
119 kind: include.kind,
120 }
121 }
122}
David Tolnay8810a542020-10-31 21:39:22 -0700123
David Tolnay97c5b862020-11-01 14:59:01 -0800124impl<'a> Deref for Includes<'a> {
125 type Target = Content<'a>;
David Tolnay8810a542020-10-31 21:39:22 -0700126
127 fn deref(&self) -> &Self::Target {
128 &self.content
129 }
130}
131
David Tolnay97c5b862020-11-01 14:59:01 -0800132impl<'a> DerefMut for Includes<'a> {
David Tolnay8810a542020-10-31 21:39:22 -0700133 fn deref_mut(&mut self) -> &mut Self::Target {
134 &mut self.content
135 }
136}