use crate::gen::out::{Content, OutFile}; use crate::syntax::{self, IncludeKind}; use std::ops::{Deref, DerefMut}; /// The complete contents of the "rust/cxx.h" header. pub static HEADER: &str = include_str!("include/cxx.h"); /// A header to #include. /// /// The cxxbridge tool does not parse or even require the given paths to exist; /// they simply go into the generated C++ code as #include lines. #[derive(Clone, PartialEq, Debug)] pub struct Include { /// The header's path, not including the enclosing quotation marks or angle /// brackets. pub path: String, /// Whether to emit `#include "path"` or `#include `. pub kind: IncludeKind, } #[derive(Default, PartialEq)] pub struct Includes<'a> { pub custom: Vec, pub algorithm: bool, pub array: bool, pub cassert: bool, pub cstddef: bool, pub cstdint: bool, pub cstring: bool, pub exception: bool, pub functional: bool, pub initializer_list: bool, pub iterator: bool, pub memory: bool, pub new: bool, pub stdexcept: bool, pub string: bool, pub type_traits: bool, pub utility: bool, pub vector: bool, pub basetsd: bool, pub sys_types: bool, pub content: Content<'a>, } impl<'a> Includes<'a> { pub fn new() -> Self { Includes::default() } pub fn insert(&mut self, include: impl Into) { self.custom.push(include.into()); } pub fn has_cxx_header(&self) -> bool { self.custom .iter() .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h") } } pub(super) fn write(out: &mut OutFile) { let header = out.header; let include = &mut out.include; let cxx_header = include.has_cxx_header(); let out = &mut include.content; if header { writeln!(out, "#pragma once"); } for include in &include.custom { match include.kind { IncludeKind::Quoted => { writeln!(out, "#include \"{}\"", include.path.escape_default()); } IncludeKind::Bracketed => { writeln!(out, "#include <{}>", include.path); } } } let Includes { custom: _, algorithm, array, cassert, cstddef, cstdint, cstring, exception, functional, initializer_list, iterator, memory, new, stdexcept, string, type_traits, utility, vector, basetsd, sys_types, content: _, } = *include; if algorithm && !cxx_header { writeln!(out, "#include "); } if array && !cxx_header { writeln!(out, "#include "); } if cassert && !cxx_header { writeln!(out, "#include "); } if cstddef && !cxx_header { writeln!(out, "#include "); } if cstdint && !cxx_header { writeln!(out, "#include "); } if cstring { writeln!(out, "#include "); } if exception && !cxx_header { writeln!(out, "#include "); } if functional { writeln!(out, "#include "); } if initializer_list && !cxx_header { writeln!(out, "#include "); } if iterator && !cxx_header { writeln!(out, "#include "); } if memory { writeln!(out, "#include "); } if new && !cxx_header { writeln!(out, "#include "); } if stdexcept && !cxx_header { writeln!(out, "#include "); } if string && !cxx_header { writeln!(out, "#include "); } if type_traits && !cxx_header { writeln!(out, "#include "); } if utility && !cxx_header { writeln!(out, "#include "); } if vector && !cxx_header { writeln!(out, "#include "); } if basetsd && !cxx_header { writeln!(out, "#if defined(_WIN32)"); writeln!(out, "#include "); } if sys_types && !cxx_header { if basetsd { writeln!(out, "#else"); } else { writeln!(out, "#if not defined(_WIN32)"); } } if sys_types && !cxx_header { writeln!(out, "#include "); } if (basetsd || sys_types) && !cxx_header { writeln!(out, "#endif"); } } impl<'i, 'a> Extend<&'i Include> for Includes<'a> { fn extend>(&mut self, iter: I) { self.custom.extend(iter.into_iter().cloned()); } } impl<'i> From<&'i syntax::Include> for Include { fn from(include: &syntax::Include) -> Self { Include { path: include.path.clone(), kind: include.kind, } } } impl<'a> Deref for Includes<'a> { type Target = Content<'a>; fn deref(&self) -> &Self::Target { &self.content } } impl<'a> DerefMut for Includes<'a> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.content } }