1use crate::gen::out::{Content, OutFile}; 2use crate::syntax::{self, IncludeKind}; 3use std::ops::{Deref, DerefMut}; 4 5/// The complete contents of the "rust/cxx.h" header. 6pub 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)] 13pub 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)] 22pub 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 46impl<'a> Includes<'a> { 47 pub fn new() -> Self { 48 Includes::default() 49 } 50 51 pub fn insert(&mut self, include: impl Into<Include>) { 52 self.custom.push(include.into()); 53 } 54 55 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 62pub(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 177impl<'i, 'a> Extend<&'i Include> for Includes<'a> { 178 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) { 179 self.custom.extend(iter.into_iter().cloned()); 180 } 181} 182 183impl<'i> From<&'i syntax::Include> for Include { 184 fn from(include: &syntax::Include) -> Self { 185 Include { 186 path: include.path.clone(), 187 kind: include.kind, 188 } 189 } 190} 191 192impl<'a> Deref for Includes<'a> { 193 type Target = Content<'a>; 194 195 fn deref(&self) -> &Self::Target { 196 &self.content 197 } 198} 199 200impl<'a> DerefMut for Includes<'a> { 201 fn deref_mut(&mut self) -> &mut Self::Target { 202 &mut self.content 203 } 204} 205