Skip to content

Commit da8358f

Browse files
committed
Add bindings for Rust std::option::Option
1 parent d5aed94 commit da8358f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1891
-24
lines changed

gen/src/builtin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) struct Builtins<'a> {
1010
pub rust_slice: bool,
1111
pub rust_box: bool,
1212
pub rust_vec: bool,
13+
pub rust_option: bool,
1314
pub rust_fn: bool,
1415
pub rust_isize: bool,
1516
pub opaque: bool,

gen/src/write.rs

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::gen::nested::NamespaceEntries;
33
use crate::gen::out::OutFile;
44
use crate::gen::{builtin, include, Opt};
55
use crate::syntax::atom::Atom::{self, *};
6-
use crate::syntax::instantiate::{ImplKey, NamedImplKey};
6+
use crate::syntax::instantiate::{ImplKey, NamedImplKey, OptionInner};
77
use crate::syntax::map::UnorderedMap as Map;
88
use crate::syntax::set::UnorderedSet;
99
use crate::syntax::symbol::{self, Symbol};
@@ -214,6 +214,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
214214
},
215215
Type::RustBox(_) => out.builtin.rust_box = true,
216216
Type::RustVec(_) => out.builtin.rust_vec = true,
217+
Type::RustOption(_) => out.builtin.rust_option = true,
217218
Type::UniquePtr(_) => out.include.memory = true,
218219
Type::SharedPtr(_) | Type::WeakPtr(_) => out.include.memory = true,
219220
Type::Str(_) => out.builtin.rust_str = true,
@@ -836,6 +837,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
836837
out.builtin.unsafe_bitcopy = true;
837838
write_type(out, &arg.ty);
838839
write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx);
840+
} else if let Type::RustOption(_) = arg.ty {
841+
write!(out, "std::move(* {})", arg.name.cxx);
839842
} else if out.types.needs_indirect_abi(&arg.ty) {
840843
out.include.utility = true;
841844
write!(out, "::std::move(*{})", arg.name.cxx);
@@ -1235,6 +1238,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
12351238
write_type(out, &ty.inner);
12361239
write!(out, ">");
12371240
}
1241+
Type::RustOption(ty) => {
1242+
write!(out, "::rust::Option<");
1243+
match &ty.inner {
1244+
Type::RustBox(_) => write_type(out, &ty.inner),
1245+
Type::Ref(r) => {
1246+
write_type_space(out, &r.inner);
1247+
if !r.mutable {
1248+
write!(out, "const ");
1249+
}
1250+
write!(out, "*");
1251+
}
1252+
_ => unreachable!(),
1253+
}
1254+
write!(out, ">");
1255+
}
12381256
Type::UniquePtr(ptr) => {
12391257
write!(out, "::std::unique_ptr<");
12401258
write_type(out, &ptr.inner);
@@ -1340,6 +1358,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
13401358
| Type::Str(_)
13411359
| Type::CxxVector(_)
13421360
| Type::RustVec(_)
1361+
| Type::RustOption(_)
13431362
| Type::SliceRef(_)
13441363
| Type::Fn(_)
13451364
| Type::Array(_) => write!(out, " "),
@@ -1354,6 +1373,12 @@ enum UniquePtr<'a> {
13541373
CxxVector(&'a Ident),
13551374
}
13561375

1376+
enum RustOption<'a> {
1377+
RustBox(&'a Ident),
1378+
Ref(&'a Ident),
1379+
MutRef(&'a Ident),
1380+
}
1381+
13571382
trait ToTypename {
13581383
fn to_typename(&self, types: &Types) -> String;
13591384
}
@@ -1375,6 +1400,18 @@ impl<'a> ToTypename for UniquePtr<'a> {
13751400
}
13761401
}
13771402

1403+
impl<'a> ToTypename for RustOption<'a> {
1404+
fn to_typename(&self, types: &Types) -> String {
1405+
match self {
1406+
RustOption::RustBox(inner) => {
1407+
format!("::rust::cxxbridge1::Box<{}>", inner.to_typename(types))
1408+
}
1409+
RustOption::Ref(inner) => format!("const {}*", inner.to_typename(types)),
1410+
RustOption::MutRef(inner) => format!("{}*", inner.to_typename(types)),
1411+
}
1412+
}
1413+
}
1414+
13781415
trait ToMangled {
13791416
fn to_mangled(&self, types: &Types) -> Symbol;
13801417
}
@@ -1396,6 +1433,22 @@ impl<'a> ToMangled for UniquePtr<'a> {
13961433
}
13971434
}
13981435

1436+
impl<'a> ToMangled for RustOption<'a> {
1437+
fn to_mangled(&self, types: &Types) -> Symbol {
1438+
match self {
1439+
RustOption::RustBox(inner) => symbol::join(&[&"Box", &inner.to_mangled(types)]),
1440+
RustOption::Ref(inner) => {
1441+
let symbol = symbol::join(&[&"const", &inner.to_mangled(types)]);
1442+
symbol
1443+
}
1444+
RustOption::MutRef(inner) => {
1445+
let symbol = symbol::join(&[&inner.to_mangled(types)]);
1446+
symbol
1447+
}
1448+
}
1449+
}
1450+
}
1451+
13991452
fn write_generic_instantiations(out: &mut OutFile) {
14001453
if out.header {
14011454
return;
@@ -1409,6 +1462,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
14091462
match *impl_key {
14101463
ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
14111464
ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
1465+
ImplKey::RustOption(ident) => write_rust_option_extern(out, ident),
14121466
ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
14131467
ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
14141468
ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
@@ -1423,6 +1477,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
14231477
match *impl_key {
14241478
ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
14251479
ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
1480+
ImplKey::RustOption(ident) => write_rust_option_impl(out, ident),
14261481
_ => {}
14271482
}
14281483
}
@@ -1501,6 +1556,53 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
15011556
);
15021557
}
15031558

1559+
fn write_rust_option_extern(out: &mut OutFile, inner: OptionInner) {
1560+
out.include.cstddef = true;
1561+
let element = match inner {
1562+
OptionInner::RustBox(key) => RustOption::RustBox(key.rust),
1563+
OptionInner::Ref(key) => {
1564+
if out.types.try_resolve(key.rust).is_none() {
1565+
return;
1566+
}
1567+
RustOption::Ref(key.rust)
1568+
}
1569+
OptionInner::MutRef(key) => {
1570+
if out.types.try_resolve(key.rust).is_none() {
1571+
return;
1572+
}
1573+
RustOption::MutRef(key.rust)
1574+
}
1575+
};
1576+
let inner = element.to_typename(out.types);
1577+
let instance = element.to_mangled(out.types);
1578+
1579+
writeln!(
1580+
out,
1581+
"void cxxbridge1$rust_option${}$new(const ::rust::Option<{}> *ptr) noexcept;",
1582+
instance, inner,
1583+
);
1584+
writeln!(
1585+
out,
1586+
"void cxxbridge1$rust_option${}$drop(::rust::Option<{}> *ptr) noexcept;",
1587+
instance, inner,
1588+
);
1589+
writeln!(
1590+
out,
1591+
"bool cxxbridge1$rust_option${}$has_value(::rust::Option<{}> const *ptr) noexcept;",
1592+
instance, inner
1593+
);
1594+
writeln!(
1595+
out,
1596+
"{}* cxxbridge1$rust_option${}$value_ptr(::rust::Option<{0}> *ptr) noexcept;",
1597+
inner, instance
1598+
);
1599+
writeln!(
1600+
out,
1601+
"void cxxbridge1$rust_option${}$set(::rust::Option<{1}> *ptr, {1}&& value) noexcept;",
1602+
instance, inner
1603+
);
1604+
}
1605+
15041606
fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) {
15051607
let resolve = out.types.resolve(&key);
15061608
let inner = resolve.name.to_fully_qualified();
@@ -1621,6 +1723,72 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
16211723
writeln!(out, "}}");
16221724
}
16231725

1726+
fn write_rust_option_impl(out: &mut OutFile, inner: OptionInner) {
1727+
let element = match inner {
1728+
OptionInner::RustBox(key) => RustOption::RustBox(key.rust),
1729+
OptionInner::Ref(key) => {
1730+
if out.types.try_resolve(key.rust).is_none() {
1731+
return;
1732+
}
1733+
RustOption::Ref(key.rust)
1734+
}
1735+
OptionInner::MutRef(key) => {
1736+
if out.types.try_resolve(key.rust).is_none() {
1737+
return;
1738+
}
1739+
RustOption::MutRef(key.rust)
1740+
}
1741+
};
1742+
let inner = element.to_typename(out.types);
1743+
let instance = element.to_mangled(out.types);
1744+
1745+
writeln!(out, "template <>");
1746+
begin_function_definition(out);
1747+
writeln!(out, "Option<{}>::Option() noexcept {{", inner);
1748+
writeln!(out, " cxxbridge1$rust_option${}$new(this);", instance);
1749+
writeln!(out, "}}");
1750+
1751+
writeln!(out, "template <>");
1752+
begin_function_definition(out);
1753+
writeln!(out, "void Option<{}>::drop() noexcept {{", inner);
1754+
writeln!(
1755+
out,
1756+
" return cxxbridge1$rust_option${}$drop(this);",
1757+
instance
1758+
);
1759+
writeln!(out, "}}");
1760+
1761+
writeln!(out, "template <>");
1762+
begin_function_definition(out);
1763+
writeln!(out, "bool Option<{}>::has_value() const noexcept {{", inner);
1764+
writeln!(
1765+
out,
1766+
" return cxxbridge1$rust_option${}$has_value(this);",
1767+
instance
1768+
);
1769+
writeln!(out, "}}");
1770+
1771+
writeln!(out, "template <>");
1772+
begin_function_definition(out);
1773+
writeln!(out, "{0}* Option<{0}>::value_ptr() noexcept {{", inner);
1774+
writeln!(
1775+
out,
1776+
" return cxxbridge1$rust_option${}$value_ptr(this);",
1777+
instance
1778+
);
1779+
writeln!(out, "}}");
1780+
1781+
writeln!(out, "template <>");
1782+
begin_function_definition(out);
1783+
writeln!(out, "void Option<{0}>::set({0}&& value) noexcept {{", inner);
1784+
writeln!(
1785+
out,
1786+
" return cxxbridge1$rust_option${}$set(this, ::std::move(value));",
1787+
instance
1788+
);
1789+
writeln!(out, "}}");
1790+
}
1791+
16241792
fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) {
16251793
let ty = UniquePtr::Ident(key.rust);
16261794
write_unique_ptr_common(out, ty);

include/cxx.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,93 @@ template <typename T>
826826
Box<T>::Box(uninit) noexcept {}
827827
#endif // CXXBRIDGE1_RUST_BOX
828828

829+
#ifndef CXXBRIDGE1_RUST_OPTION
830+
template <typename T>
831+
class Option final {
832+
public:
833+
Option() noexcept;
834+
Option(Option&&) noexcept;
835+
Option(T&&) noexcept;
836+
~Option() noexcept;
837+
838+
const T *operator->() const;
839+
const T &operator*() const;
840+
T *operator->();
841+
T &operator*();
842+
843+
Option<T>& operator=(Option&&) noexcept;
844+
845+
bool has_value() const noexcept;
846+
T& value() noexcept;
847+
void reset();
848+
void set(T&&) noexcept;
849+
private:
850+
void* empty_;
851+
852+
T* value_ptr() noexcept;
853+
void drop() noexcept;
854+
};
855+
#endif // CXXBRIDGE1_RUST_OPTION
856+
857+
#ifndef CXXBRIDGE1_RUST_OPTION
858+
#define CXXBRIDGE1_RUST_OPTION
859+
template <typename T>
860+
Option<T>::Option(Option&& other) noexcept {
861+
new (this) Option();
862+
if (other.has_value()) {
863+
set(std::move(other.value()));
864+
}
865+
new (&other) Option();
866+
}
867+
868+
template <typename T>
869+
Option<T>::~Option() noexcept {
870+
this->drop();
871+
}
872+
873+
template <typename T>
874+
Option<T>& Option<T>::operator=(Option&& other) noexcept {
875+
this->reset();
876+
if (other.has_value()) {
877+
set(std::move(other.value()));
878+
}
879+
new (&other) Option();
880+
return *this;
881+
}
882+
883+
template <typename T>
884+
const T *Option<T>::operator->() const {
885+
return &value();
886+
}
887+
888+
template <typename T>
889+
const T &Option<T>::operator*() const {
890+
return value();
891+
}
892+
893+
template <typename T>
894+
T *Option<T>::operator->() {
895+
return &value();
896+
}
897+
898+
template <typename T>
899+
T &Option<T>::operator*() {
900+
return value();
901+
}
902+
903+
template <typename T>
904+
T &Option<T>::value() noexcept {
905+
return *value_ptr();
906+
}
907+
908+
template <typename T>
909+
void Option<T>::reset() {
910+
this->drop();
911+
new (this) Option();
912+
}
913+
914+
#endif // CXXBRIDGE1_RUST_OPTION
915+
829916
#ifndef CXXBRIDGE1_RUST_VEC
830917
#define CXXBRIDGE1_RUST_VEC
831918
template <typename T>

macro/src/derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::syntax::{derive, Enum, Struct, Trait};
1+
use crate::syntax::{derive, Enum, Struct};
22
use proc_macro2::{Ident, Span, TokenStream};
33
use quote::{quote, quote_spanned, ToTokens};
44

0 commit comments

Comments
 (0)