133d722a9Sopenharmony_ciuse crate::gen::out::{Content, OutFile};
233d722a9Sopenharmony_ciuse crate::syntax::{self, IncludeKind};
333d722a9Sopenharmony_ciuse std::ops::{Deref, DerefMut};
433d722a9Sopenharmony_ci
533d722a9Sopenharmony_ci/// The complete contents of the "rust/cxx.h" header.
633d722a9Sopenharmony_cipub static HEADER: &str = include_str!("include/cxx.h");
733d722a9Sopenharmony_ci
833d722a9Sopenharmony_ci/// A header to #include.
933d722a9Sopenharmony_ci///
1033d722a9Sopenharmony_ci/// The cxxbridge tool does not parse or even require the given paths to exist;
1133d722a9Sopenharmony_ci/// they simply go into the generated C++ code as #include lines.
1233d722a9Sopenharmony_ci#[derive(Clone, PartialEq, Debug)]
1333d722a9Sopenharmony_cipub struct Include {
1433d722a9Sopenharmony_ci    /// The header's path, not including the enclosing quotation marks or angle
1533d722a9Sopenharmony_ci    /// brackets.
1633d722a9Sopenharmony_ci    pub path: String,
1733d722a9Sopenharmony_ci    /// Whether to emit `#include "path"` or `#include <path>`.
1833d722a9Sopenharmony_ci    pub kind: IncludeKind,
1933d722a9Sopenharmony_ci}
2033d722a9Sopenharmony_ci
2133d722a9Sopenharmony_ci#[derive(Default, PartialEq)]
2233d722a9Sopenharmony_cipub struct Includes<'a> {
2333d722a9Sopenharmony_ci    pub custom: Vec<Include>,
2433d722a9Sopenharmony_ci    pub algorithm: bool,
2533d722a9Sopenharmony_ci    pub array: bool,
2633d722a9Sopenharmony_ci    pub cassert: bool,
2733d722a9Sopenharmony_ci    pub cstddef: bool,
2833d722a9Sopenharmony_ci    pub cstdint: bool,
2933d722a9Sopenharmony_ci    pub cstring: bool,
3033d722a9Sopenharmony_ci    pub exception: bool,
3133d722a9Sopenharmony_ci    pub functional: bool,
3233d722a9Sopenharmony_ci    pub initializer_list: bool,
3333d722a9Sopenharmony_ci    pub iterator: bool,
3433d722a9Sopenharmony_ci    pub memory: bool,
3533d722a9Sopenharmony_ci    pub new: bool,
3633d722a9Sopenharmony_ci    pub stdexcept: bool,
3733d722a9Sopenharmony_ci    pub string: bool,
3833d722a9Sopenharmony_ci    pub type_traits: bool,
3933d722a9Sopenharmony_ci    pub utility: bool,
4033d722a9Sopenharmony_ci    pub vector: bool,
4133d722a9Sopenharmony_ci    pub basetsd: bool,
4233d722a9Sopenharmony_ci    pub sys_types: bool,
4333d722a9Sopenharmony_ci    pub content: Content<'a>,
4433d722a9Sopenharmony_ci}
4533d722a9Sopenharmony_ci
4633d722a9Sopenharmony_ciimpl<'a> Includes<'a> {
4733d722a9Sopenharmony_ci    pub fn new() -> Self {
4833d722a9Sopenharmony_ci        Includes::default()
4933d722a9Sopenharmony_ci    }
5033d722a9Sopenharmony_ci
5133d722a9Sopenharmony_ci    pub fn insert(&mut self, include: impl Into<Include>) {
5233d722a9Sopenharmony_ci        self.custom.push(include.into());
5333d722a9Sopenharmony_ci    }
5433d722a9Sopenharmony_ci
5533d722a9Sopenharmony_ci    pub fn has_cxx_header(&self) -> bool {
5633d722a9Sopenharmony_ci        self.custom
5733d722a9Sopenharmony_ci            .iter()
5833d722a9Sopenharmony_ci            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
5933d722a9Sopenharmony_ci    }
6033d722a9Sopenharmony_ci}
6133d722a9Sopenharmony_ci
6233d722a9Sopenharmony_cipub(super) fn write(out: &mut OutFile) {
6333d722a9Sopenharmony_ci    let header = out.header;
6433d722a9Sopenharmony_ci    let include = &mut out.include;
6533d722a9Sopenharmony_ci    let cxx_header = include.has_cxx_header();
6633d722a9Sopenharmony_ci    let out = &mut include.content;
6733d722a9Sopenharmony_ci
6833d722a9Sopenharmony_ci    if header {
6933d722a9Sopenharmony_ci        writeln!(out, "#pragma once");
7033d722a9Sopenharmony_ci    }
7133d722a9Sopenharmony_ci
7233d722a9Sopenharmony_ci    for include in &include.custom {
7333d722a9Sopenharmony_ci        match include.kind {
7433d722a9Sopenharmony_ci            IncludeKind::Quoted => {
7533d722a9Sopenharmony_ci                writeln!(out, "#include \"{}\"", include.path.escape_default());
7633d722a9Sopenharmony_ci            }
7733d722a9Sopenharmony_ci            IncludeKind::Bracketed => {
7833d722a9Sopenharmony_ci                writeln!(out, "#include <{}>", include.path);
7933d722a9Sopenharmony_ci            }
8033d722a9Sopenharmony_ci        }
8133d722a9Sopenharmony_ci    }
8233d722a9Sopenharmony_ci
8333d722a9Sopenharmony_ci    let Includes {
8433d722a9Sopenharmony_ci        custom: _,
8533d722a9Sopenharmony_ci        algorithm,
8633d722a9Sopenharmony_ci        array,
8733d722a9Sopenharmony_ci        cassert,
8833d722a9Sopenharmony_ci        cstddef,
8933d722a9Sopenharmony_ci        cstdint,
9033d722a9Sopenharmony_ci        cstring,
9133d722a9Sopenharmony_ci        exception,
9233d722a9Sopenharmony_ci        functional,
9333d722a9Sopenharmony_ci        initializer_list,
9433d722a9Sopenharmony_ci        iterator,
9533d722a9Sopenharmony_ci        memory,
9633d722a9Sopenharmony_ci        new,
9733d722a9Sopenharmony_ci        stdexcept,
9833d722a9Sopenharmony_ci        string,
9933d722a9Sopenharmony_ci        type_traits,
10033d722a9Sopenharmony_ci        utility,
10133d722a9Sopenharmony_ci        vector,
10233d722a9Sopenharmony_ci        basetsd,
10333d722a9Sopenharmony_ci        sys_types,
10433d722a9Sopenharmony_ci        content: _,
10533d722a9Sopenharmony_ci    } = *include;
10633d722a9Sopenharmony_ci
10733d722a9Sopenharmony_ci    if algorithm && !cxx_header {
10833d722a9Sopenharmony_ci        writeln!(out, "#include <algorithm>");
10933d722a9Sopenharmony_ci    }
11033d722a9Sopenharmony_ci    if array && !cxx_header {
11133d722a9Sopenharmony_ci        writeln!(out, "#include <array>");
11233d722a9Sopenharmony_ci    }
11333d722a9Sopenharmony_ci    if cassert && !cxx_header {
11433d722a9Sopenharmony_ci        writeln!(out, "#include <cassert>");
11533d722a9Sopenharmony_ci    }
11633d722a9Sopenharmony_ci    if cstddef && !cxx_header {
11733d722a9Sopenharmony_ci        writeln!(out, "#include <cstddef>");
11833d722a9Sopenharmony_ci    }
11933d722a9Sopenharmony_ci    if cstdint && !cxx_header {
12033d722a9Sopenharmony_ci        writeln!(out, "#include <cstdint>");
12133d722a9Sopenharmony_ci    }
12233d722a9Sopenharmony_ci    if cstring {
12333d722a9Sopenharmony_ci        writeln!(out, "#include <cstring>");
12433d722a9Sopenharmony_ci    }
12533d722a9Sopenharmony_ci    if exception && !cxx_header {
12633d722a9Sopenharmony_ci        writeln!(out, "#include <exception>");
12733d722a9Sopenharmony_ci    }
12833d722a9Sopenharmony_ci    if functional {
12933d722a9Sopenharmony_ci        writeln!(out, "#include <functional>");
13033d722a9Sopenharmony_ci    }
13133d722a9Sopenharmony_ci    if initializer_list && !cxx_header {
13233d722a9Sopenharmony_ci        writeln!(out, "#include <initializer_list>");
13333d722a9Sopenharmony_ci    }
13433d722a9Sopenharmony_ci    if iterator && !cxx_header {
13533d722a9Sopenharmony_ci        writeln!(out, "#include <iterator>");
13633d722a9Sopenharmony_ci    }
13733d722a9Sopenharmony_ci    if memory {
13833d722a9Sopenharmony_ci        writeln!(out, "#include <memory>");
13933d722a9Sopenharmony_ci    }
14033d722a9Sopenharmony_ci    if new && !cxx_header {
14133d722a9Sopenharmony_ci        writeln!(out, "#include <new>");
14233d722a9Sopenharmony_ci    }
14333d722a9Sopenharmony_ci    if stdexcept && !cxx_header {
14433d722a9Sopenharmony_ci        writeln!(out, "#include <stdexcept>");
14533d722a9Sopenharmony_ci    }
14633d722a9Sopenharmony_ci    if string && !cxx_header {
14733d722a9Sopenharmony_ci        writeln!(out, "#include <string>");
14833d722a9Sopenharmony_ci    }
14933d722a9Sopenharmony_ci    if type_traits && !cxx_header {
15033d722a9Sopenharmony_ci        writeln!(out, "#include <type_traits>");
15133d722a9Sopenharmony_ci    }
15233d722a9Sopenharmony_ci    if utility && !cxx_header {
15333d722a9Sopenharmony_ci        writeln!(out, "#include <utility>");
15433d722a9Sopenharmony_ci    }
15533d722a9Sopenharmony_ci    if vector && !cxx_header {
15633d722a9Sopenharmony_ci        writeln!(out, "#include <vector>");
15733d722a9Sopenharmony_ci    }
15833d722a9Sopenharmony_ci    if basetsd && !cxx_header {
15933d722a9Sopenharmony_ci        writeln!(out, "#if defined(_WIN32)");
16033d722a9Sopenharmony_ci        writeln!(out, "#include <basetsd.h>");
16133d722a9Sopenharmony_ci    }
16233d722a9Sopenharmony_ci    if sys_types && !cxx_header {
16333d722a9Sopenharmony_ci        if basetsd {
16433d722a9Sopenharmony_ci            writeln!(out, "#else");
16533d722a9Sopenharmony_ci        } else {
16633d722a9Sopenharmony_ci            writeln!(out, "#if not defined(_WIN32)");
16733d722a9Sopenharmony_ci        }
16833d722a9Sopenharmony_ci    }
16933d722a9Sopenharmony_ci    if sys_types && !cxx_header {
17033d722a9Sopenharmony_ci        writeln!(out, "#include <sys/types.h>");
17133d722a9Sopenharmony_ci    }
17233d722a9Sopenharmony_ci    if (basetsd || sys_types) && !cxx_header {
17333d722a9Sopenharmony_ci        writeln!(out, "#endif");
17433d722a9Sopenharmony_ci    }
17533d722a9Sopenharmony_ci}
17633d722a9Sopenharmony_ci
17733d722a9Sopenharmony_ciimpl<'i, 'a> Extend<&'i Include> for Includes<'a> {
17833d722a9Sopenharmony_ci    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
17933d722a9Sopenharmony_ci        self.custom.extend(iter.into_iter().cloned());
18033d722a9Sopenharmony_ci    }
18133d722a9Sopenharmony_ci}
18233d722a9Sopenharmony_ci
18333d722a9Sopenharmony_ciimpl<'i> From<&'i syntax::Include> for Include {
18433d722a9Sopenharmony_ci    fn from(include: &syntax::Include) -> Self {
18533d722a9Sopenharmony_ci        Include {
18633d722a9Sopenharmony_ci            path: include.path.clone(),
18733d722a9Sopenharmony_ci            kind: include.kind,
18833d722a9Sopenharmony_ci        }
18933d722a9Sopenharmony_ci    }
19033d722a9Sopenharmony_ci}
19133d722a9Sopenharmony_ci
19233d722a9Sopenharmony_ciimpl<'a> Deref for Includes<'a> {
19333d722a9Sopenharmony_ci    type Target = Content<'a>;
19433d722a9Sopenharmony_ci
19533d722a9Sopenharmony_ci    fn deref(&self) -> &Self::Target {
19633d722a9Sopenharmony_ci        &self.content
19733d722a9Sopenharmony_ci    }
19833d722a9Sopenharmony_ci}
19933d722a9Sopenharmony_ci
20033d722a9Sopenharmony_ciimpl<'a> DerefMut for Includes<'a> {
20133d722a9Sopenharmony_ci    fn deref_mut(&mut self) -> &mut Self::Target {
20233d722a9Sopenharmony_ci        &mut self.content
20333d722a9Sopenharmony_ci    }
20433d722a9Sopenharmony_ci}
205