Provide more struct definitions where needed

This commit is contained in:
David Tolnay 2020-03-17 21:18:40 -07:00
parent 26ad0bd98c
commit b7a7cb6785
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
3 changed files with 89 additions and 20 deletions

View File

@ -29,8 +29,10 @@ fn find_line(line: &str) -> Option<usize> {
#[derive(Default)]
pub struct Includes {
custom: Vec<String>,
pub array: bool,
pub cstdint: bool,
pub cstring: bool,
pub exception: bool,
pub memory: bool,
pub string: bool,
pub type_traits: bool,
@ -51,12 +53,18 @@ impl Display for Includes {
for include in &self.custom {
writeln!(f, "#include \"{}\"", include.escape_default())?;
}
if self.array {
writeln!(f, "#include <array>")?;
}
if self.cstdint {
writeln!(f, "#include <cstdint>")?;
}
if self.cstring {
writeln!(f, "#include <cstring>")?;
}
if self.exception {
writeln!(f, "#include <exception>")?;
}
if self.memory {
writeln!(f, "#include <memory>")?;
}

View File

@ -97,47 +97,84 @@ fn write_includes(out: &mut OutFile, types: &Types) {
}
fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
let mut needs_rust_string = false;
let mut needs_rust_str = false;
let mut needs_rust_box = false;
for ty in types {
if let Type::RustBox(_) = ty {
needs_rust_box = true;
break;
match ty {
Type::RustBox(_) => {
out.include.type_traits = true;
needs_rust_box = true;
}
Type::Str(_) => {
out.include.cstdint = true;
out.include.string = true;
needs_rust_str = true;
}
ty if ty == RustString => {
out.include.array = true;
out.include.cstdint = true;
out.include.string = true;
needs_rust_string = true;
}
_ => {}
}
}
let mut needs_rust_error = false;
let mut needs_unsafe_bitcopy = false;
let mut needs_manually_drop = false;
let mut needs_maybe_uninit = false;
for api in apis {
if let Api::RustFunction(efn) = api {
for arg in &efn.args {
if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
needs_manually_drop = true;
break;
match api {
Api::CxxFunction(efn) if !out.header => {
for arg in &efn.args {
if arg.ty == RustString {
needs_unsafe_bitcopy = true;
break;
}
}
}
if let Some(ret) = &efn.ret {
if types.needs_indirect_abi(ret) {
needs_maybe_uninit = true;
Api::RustFunction(efn) if !out.header => {
if efn.throws {
out.include.exception = true;
needs_rust_error = true;
}
for arg in &efn.args {
if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
needs_manually_drop = true;
break;
}
}
if let Some(ret) = &efn.ret {
if types.needs_indirect_abi(ret) {
needs_maybe_uninit = true;
}
}
}
_ => {}
}
}
out.begin_block("namespace rust");
out.begin_block("inline namespace cxxbridge02");
if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
if needs_rust_string
|| needs_rust_str
|| needs_rust_box
|| needs_rust_error
|| needs_unsafe_bitcopy
|| needs_manually_drop
|| needs_maybe_uninit
{
writeln!(out, "// #include \"rust/cxx.h\"");
}
if needs_rust_box {
out.next_section();
for line in include::get("CXXBRIDGE02_RUST_BOX").lines() {
if !line.trim_start().starts_with("//") {
writeln!(out, "{}", line);
}
}
}
write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
if needs_manually_drop {
out.next_section();
@ -166,6 +203,17 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
out.end_block("namespace rust");
}
fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
if needed {
out.next_section();
for line in include::get(section).lines() {
if !line.trim_start().starts_with("//") {
writeln!(out, "{}", line);
}
}
}
}
fn write_struct(out: &mut OutFile, strct: &Struct) {
for line in strct.doc.to_string().lines() {
writeln!(out, "//{}", line);

View File

@ -1,6 +1,7 @@
#pragma once
#include <array>
#include <cstdint>
#include <exception>
#include <iosfwd>
#include <string>
#include <type_traits>
@ -10,6 +11,8 @@ inline namespace cxxbridge02 {
struct unsafe_bitcopy_t;
#ifndef CXXBRIDGE02_RUST_STRING
#define CXXBRIDGE02_RUST_STRING
class String final {
public:
String() noexcept;
@ -37,7 +40,10 @@ private:
// Size and alignment statically verified by rust_string.rs.
std::array<uintptr_t, 3> repr;
};
#endif // CXXBRIDGE02_RUST_STRING
#ifndef CXXBRIDGE02_RUST_STR
#define CXXBRIDGE02_RUST_STR
class Str final {
public:
Str() noexcept;
@ -70,6 +76,7 @@ public:
private:
Repr repr;
};
#endif // CXXBRIDGE02_RUST_STR
#ifndef CXXBRIDGE02_RUST_BOX
#define CXXBRIDGE02_RUST_BOX
@ -138,6 +145,8 @@ private:
};
#endif // CXXBRIDGE02_RUST_BOX
#ifndef CXXBRIDGE02_RUST_ERROR
#define CXXBRIDGE02_RUST_ERROR
class Error final : std::exception {
public:
Error(const Error &);
@ -149,6 +158,7 @@ public:
private:
Str::Repr msg;
};
#endif // CXXBRIDGE02_RUST_ERROR
std::ostream &operator<<(std::ostream &, const String &);
std::ostream &operator<<(std::ostream &, const Str &);
@ -159,10 +169,13 @@ using str = Str;
template <class T> using box = Box<T>;
using error = Error;
#ifndef CXXBRIDGE02_RUST_BITCOPY
#define CXXBRIDGE02_RUST_BITCOPY
struct unsafe_bitcopy_t {
explicit unsafe_bitcopy_t() = default;
};
constexpr unsafe_bitcopy_t unsafe_bitcopy{};
#endif // CXXBRIDGE02_RUST_BITCOPY
} // namespace cxxbridge02
} // namespace rust