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