cxx_build/gen/
include.rs

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(crate) 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 limits: bool,
35    pub memory: bool,
36    pub new: bool,
37    pub ranges: bool,
38    pub stdexcept: bool,
39    pub string: bool,
40    pub string_view: bool,
41    pub type_traits: bool,
42    pub utility: bool,
43    pub vector: bool,
44    pub basetsd: bool,
45    pub sys_types: bool,
46    pub content: Content<'a>,
47}
48
49impl<'a> Includes<'a> {
50    pub(crate) fn new() -> Self {
51        Includes::default()
52    }
53
54    pub(crate) fn insert(&mut self, include: impl Into<Include>) {
55        self.custom.push(include.into());
56    }
57
58    pub(crate) fn has_cxx_header(&self) -> bool {
59        self.custom
60            .iter()
61            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
62    }
63}
64
65pub(super) fn write(out: &mut OutFile) {
66    let header = out.header;
67    let include = &mut out.include;
68    let cxx_header = include.has_cxx_header();
69    let out = &mut include.content;
70
71    if header {
72        writeln!(out, "#pragma once");
73    }
74
75    for include in &include.custom {
76        match include.kind {
77            IncludeKind::Quoted => {
78                writeln!(out, "#include \"{}\"", include.path.escape_default());
79            }
80            IncludeKind::Bracketed => {
81                writeln!(out, "#include <{}>", include.path);
82            }
83        }
84    }
85
86    let Includes {
87        custom: _,
88        algorithm,
89        array,
90        cassert,
91        cstddef,
92        cstdint,
93        cstring,
94        exception,
95        functional,
96        initializer_list,
97        iterator,
98        limits,
99        memory,
100        new,
101        ranges,
102        stdexcept,
103        string,
104        string_view,
105        type_traits,
106        utility,
107        vector,
108        basetsd,
109        sys_types,
110        content: _,
111    } = *include;
112
113    if algorithm && !cxx_header {
114        writeln!(out, "#include <algorithm>");
115    }
116    if array && !cxx_header {
117        writeln!(out, "#include <array>");
118    }
119    if cassert && !cxx_header {
120        writeln!(out, "#include <cassert>");
121    }
122    if cstddef && !cxx_header {
123        writeln!(out, "#include <cstddef>");
124    }
125    if cstdint && !cxx_header {
126        writeln!(out, "#include <cstdint>");
127    }
128    if cstring {
129        writeln!(out, "#include <cstring>");
130    }
131    if exception && !cxx_header {
132        writeln!(out, "#include <exception>");
133    }
134    if functional {
135        writeln!(out, "#include <functional>");
136    }
137    if initializer_list && !cxx_header {
138        writeln!(out, "#include <initializer_list>");
139    }
140    if iterator && !cxx_header {
141        writeln!(out, "#include <iterator>");
142    }
143    if limits {
144        writeln!(out, "#include <limits>");
145    }
146    if memory {
147        writeln!(out, "#include <memory>");
148    }
149    if new && !cxx_header {
150        writeln!(out, "#include <new>");
151    }
152    if stdexcept && !cxx_header {
153        writeln!(out, "#include <stdexcept>");
154    }
155    if string && !cxx_header {
156        writeln!(out, "#include <string>");
157    }
158    if type_traits && !cxx_header {
159        writeln!(out, "#include <type_traits>");
160    }
161    if utility && !cxx_header {
162        writeln!(out, "#include <utility>");
163    }
164    if vector && !cxx_header {
165        writeln!(out, "#include <vector>");
166    }
167    if basetsd && !cxx_header {
168        writeln!(out, "#if defined(_WIN32)");
169        writeln!(out, "#include <basetsd.h>");
170    }
171    if sys_types && !cxx_header {
172        if basetsd {
173            writeln!(out, "#else");
174        } else {
175            writeln!(out, "#if not defined(_WIN32)");
176        }
177    }
178    if sys_types && !cxx_header {
179        writeln!(out, "#include <sys/types.h>");
180    }
181    if (basetsd || sys_types) && !cxx_header {
182        writeln!(out, "#endif");
183    }
184    if string_view && !cxx_header {
185        writeln!(out, "#if __cplusplus >= 201703L");
186        writeln!(out, "#include <string_view>");
187        writeln!(out, "#endif");
188    }
189    if ranges && !cxx_header {
190        writeln!(out, "#if __cplusplus >= 202002L");
191        writeln!(out, "#include <ranges>");
192        writeln!(out, "#endif");
193    }
194}
195
196impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
197    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
198        self.custom.extend(iter.into_iter().cloned());
199    }
200}
201
202impl From<&syntax::Include> for Include {
203    fn from(include: &syntax::Include) -> Self {
204        Include {
205            path: include.path.clone(),
206            kind: include.kind,
207        }
208    }
209}
210
211impl<'a> Deref for Includes<'a> {
212    type Target = Content<'a>;
213
214    fn deref(&self) -> &Self::Target {
215        &self.content
216    }
217}
218
219impl<'a> DerefMut for Includes<'a> {
220    fn deref_mut(&mut self) -> &mut Self::Target {
221        &mut self.content
222    }
223}