Skip to content

Commit

Permalink
Support Option<Vec> and Option<String>
Browse files Browse the repository at this point in the history
  • Loading branch information
kuecks committed Sep 3, 2024
1 parent 017a96a commit 70610dc
Show file tree
Hide file tree
Showing 19 changed files with 1,246 additions and 475 deletions.
2 changes: 2 additions & 0 deletions gen/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub(super) fn write(out: &mut OutFile) {
let out = &mut builtin.content;

if builtin.rust_option {
builtin.rust_string = true;
builtin.rust_vec = true;
builtin.rust_box = true;
}

Expand Down
197 changes: 159 additions & 38 deletions gen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,9 +820,26 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
if i > 0 {
write!(out, ", ");
}
if let Type::RustBox(_) | Type::RustOption(_) = &arg.ty {
if let Type::RustBox(_) = &arg.ty {
write_type(out, &arg.ty);
write!(out, "::from_raw({})", arg.name.cxx);
} else if let Type::RustOption(inner) = &arg.ty {
match &inner.inner {
Type::RustVec(_) => {
out.builtin.unsafe_bitcopy = true;
write_type(out, &arg.ty);
write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx,);
}
Type::Ident(ty) if ty.rust == RustString => {
out.builtin.unsafe_bitcopy = true;
write_type(out, &arg.ty);
write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx,);
}
_ => {
write_type(out, &arg.ty);
write!(out, "::from_raw({})", arg.name.cxx);
}
}
} else if let Type::UniquePtr(_) = &arg.ty {
write_type(out, &arg.ty);
write!(out, "({})", arg.name.cxx);
Expand All @@ -837,6 +854,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
out.builtin.unsafe_bitcopy = true;
write_type(out, &arg.ty);
write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx);
} else if let Type::RustOption(_) = arg.ty {
write!(out, "std::move(* {})", arg.name.cxx);
} else if out.types.needs_indirect_abi(&arg.ty) {
out.include.utility = true;
write!(out, "::std::move(*{})", arg.name.cxx);
Expand All @@ -846,7 +865,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
}
write!(out, ")");
match &efn.ret {
Some(Type::RustBox(_) | Type::RustOption(_)) => write!(out, ".into_raw()"),
Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
Some(Type::RustOption(inner)) => match inner.inner {
Type::Ident(_) | Type::RustVec(_) => {}
_ => write!(out, ".into_raw()"),
},
Some(Type::UniquePtr(_)) => write!(out, ".release()"),
Some(Type::Str(_) | Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
_ => {}
Expand Down Expand Up @@ -1051,10 +1074,17 @@ fn write_rust_function_shim_impl(
} else if let Some(ret) = &sig.ret {
write!(out, "return ");
match ret {
Type::RustBox(_) | Type::RustOption(_) => {
Type::RustBox(_) => {
write_type(out, ret);
write!(out, "::from_raw(");
}
Type::RustOption(inner) => match inner.inner {
Type::Ident(_) | Type::RustVec(_) => {}
_ => {
write_type(out, ret);
write!(out, "::from_raw(");
}
}
Type::UniquePtr(_) => {
write_type(out, ret);
write!(out, "(");
Expand Down Expand Up @@ -1092,7 +1122,11 @@ fn write_rust_function_shim_impl(
}
write!(out, "{}", arg.name.cxx);
match &arg.ty {
Type::RustBox(_) | Type::RustOption(_) => write!(out, ".into_raw()"),
Type::RustBox(_) => write!(out, ".into_raw()"),
Type::RustOption(inner) => match inner.inner {
Type::Ident(_) | Type::RustVec(_) => write!(out, "$.value"),
_ => write!(out, ".into_raw()"),
},
Type::UniquePtr(_) => write!(out, ".release()"),
ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
_ => {}
Expand All @@ -1114,15 +1148,21 @@ fn write_rust_function_shim_impl(
}
write!(out, ")");
if !indirect_return {
if let Some(
Type::RustBox(_)
| Type::UniquePtr(_)
| Type::Str(_)
| Type::SliceRef(_)
| Type::RustOption(_),
) = &sig.ret
{
write!(out, ")");
if let Some(ret) = &sig.ret {
if let
Type::RustBox(_)
| Type::UniquePtr(_)
| Type::Str(_)
| Type::SliceRef(_)
= ret
{
write!(out, ")");
} else if let Type::RustOption(inner) = &ret {
match &inner.inner {
Type::Ident(_) | Type::RustVec(_) => {}
_ => write!(out, ")"),
}
}
}
}
writeln!(out, ";");
Expand Down Expand Up @@ -1172,15 +1212,22 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
}
write!(out, "*");
}
Type::RustOption(ty) => write_indirect_return_type(out, &ty.inner),
Type::RustOption(ty) => match &ty.inner {
Type::RustBox(_) | Type::Ref(_) => write_indirect_return_type(out, &ty.inner),
_ => {
write!(out, "::rust::Option<");
write_indirect_return_type(out, &ty.inner);
write!(out, ">");
}
},
_ => write_type(out, ty),
}
}

fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
write_indirect_return_type(out, ty);
match ty {
Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) | Type::RustOption(_) => {}
Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
Type::Str(_) | Type::SliceRef(_) => write!(out, " "),
_ => write_space_after_type(out, ty),
}
Expand All @@ -1200,6 +1247,11 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: Option<&Type>) {
write!(out, "const ");
}
write!(out, "*");
}
Type::RustVec(_) | Type::Ident(_) => {
if out.types.needs_indirect_abi(&ty.inner) {
write!(out, "void ");
}
}
_ => unreachable!(),
},
Expand Down Expand Up @@ -1237,7 +1289,11 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
}
write!(out, "*");
}
_ => unreachable!(),
_ => {
write!(out, "::rust::Option<");
write_type_space(out, &ty.inner);
write!(out, "> const ");
}
},
_ => write_type_space(out, &arg.ty),
}
Expand Down Expand Up @@ -1398,6 +1454,8 @@ enum RustOption<'a> {
MutRef(&'a Ident),
RefVec(&'a Ident),
MutRefVec(&'a Ident),
Vec(&'a Ident),
Ident(&'a Ident),
}

trait ToTypename {
Expand Down Expand Up @@ -1436,6 +1494,10 @@ impl<'a> ToTypename for RustOption<'a> {
RustOption::MutRefVec(inner) => {
format!("::rust::cxxbridge1::Vec<{}>&", inner.to_typename(types))
}
RustOption::Vec(inner) => {
format!("::rust::cxxbridge1::Vec<{}>", inner.to_typename(types))
}
RustOption::Ident(ident) => ident.to_typename(types),
}
}
}
Expand Down Expand Up @@ -1464,13 +1526,17 @@ impl<'a> ToMangled for UniquePtr<'a> {
impl<'a> ToMangled for RustOption<'a> {
fn to_mangled(&self, types: &Types) -> Symbol {
match self {
RustOption::RustBox(inner) => symbol::join(&[&"Box", &inner.to_mangled(types)]),
RustOption::Ref(inner) => symbol::join(&[&"const", &inner.to_mangled(types)]),
RustOption::MutRef(inner) => symbol::join(&[&inner.to_mangled(types)]),
RustOption::RustBox(inner) => symbol::join(&[&"rust_box", &inner.to_mangled(types)]),
RustOption::Ref(inner) => symbol::join(&[&"const", &"ref", &inner.to_mangled(types)]),
RustOption::MutRef(inner) => symbol::join(&[&"ref", &inner.to_mangled(types)]),
RustOption::RefVec(inner) => {
symbol::join(&[&"const", &"Vec", &inner.to_mangled(types)])
symbol::join(&[&"const", &"ref", &"rust_vec", &inner.to_mangled(types)])
}
RustOption::MutRefVec(inner) => {
symbol::join(&[&"ref", &"rust_vec", &inner.to_mangled(types)])
}
RustOption::MutRefVec(inner) => symbol::join(&[&"Vec", &inner.to_mangled(types)]),
RustOption::Vec(inner) => symbol::join(&[&"rust_vec", &inner.to_mangled(types)]),
RustOption::Ident(ident) => symbol::join(&[&ident.to_mangled(types)]),
}
}
}
Expand Down Expand Up @@ -1584,27 +1650,27 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {

fn write_rust_option_extern(out: &mut OutFile, inner: OptionInner) {
out.include.cstddef = true;
let (element, is_const, value_type) = match inner {
let (element, is_const, is_direct, value_type) = match inner {
OptionInner::RustBox(key) => {
let element = RustOption::RustBox(key.rust);
let value_type = element.to_typename(out.types);
(element, false, value_type)
(element, false, false, value_type)
}
OptionInner::Ref(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
let resolve = out.types.resolve(&key);
let value_type = resolve.name.to_fully_qualified();
(RustOption::Ref(key.rust), true, value_type)
(RustOption::Ref(key.rust), true, false, value_type)
}
OptionInner::MutRef(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
let resolve = out.types.resolve(&key);
let value_type = resolve.name.to_fully_qualified();
(RustOption::MutRef(key.rust), false, value_type)
(RustOption::MutRef(key.rust), false, false, value_type)
}
OptionInner::RefVec(key) => {
if out.types.try_resolve(key.rust).is_none() {
Expand All @@ -1615,7 +1681,7 @@ fn write_rust_option_extern(out: &mut OutFile, inner: OptionInner) {
"::rust::cxxbridge1::Vec<{}>",
resolve.name.to_fully_qualified()
);
(RustOption::RefVec(key.rust), true, value_type)
(RustOption::RefVec(key.rust), true, false, value_type)
}
OptionInner::MutRefVec(key) => {
if out.types.try_resolve(key.rust).is_none() {
Expand All @@ -1626,7 +1692,26 @@ fn write_rust_option_extern(out: &mut OutFile, inner: OptionInner) {
"::rust::cxxbridge1::Vec<{}>",
resolve.name.to_fully_qualified()
);
(RustOption::MutRefVec(key.rust), false, value_type)
(RustOption::MutRefVec(key.rust), false, false, value_type)
}
OptionInner::Vec(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
let resolve = out.types.resolve(&key);
let value_type = format!(
"::rust::cxxbridge1::Vec<{}>",
resolve.name.to_fully_qualified()
);
(RustOption::Vec(key.rust), false, true, value_type)
}
OptionInner::Ident(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
let resolve = out.types.resolve(&key);
let value_type = resolve.name.to_fully_qualified();
(RustOption::Ident(key.rust), false, true, value_type)
}
};
let inner = element.to_typename(out.types);
Expand Down Expand Up @@ -1658,6 +1743,22 @@ fn write_rust_option_extern(out: &mut OutFile, inner: OptionInner) {
"void cxxbridge1$rust_option${}$set(::rust::Option<{}> *ptr, {} const *value) noexcept;",
instance, inner, value_type
);
} else if is_direct {
writeln!(
out,
"{} const * cxxbridge1$rust_option${}$value_const(::rust::Option<{}> const *ptr) noexcept;",
value_type, instance, inner
);
writeln!(
out,
"{}* cxxbridge1$rust_option${}$value(::rust::Option<{}> *ptr) noexcept;",
value_type, instance, inner
);
writeln!(
out,
"void cxxbridge1$rust_option${}$set(::rust::Option<{}> *ptr, {} value) noexcept;",
instance, inner, value_type
);
} else {
writeln!(
out,
Expand Down Expand Up @@ -1798,31 +1899,43 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
}

fn write_rust_option_impl(out: &mut OutFile, inner: OptionInner) {
let (element, is_const, value_needs_ref) = match inner {
OptionInner::RustBox(key) => (RustOption::RustBox(key.rust), false, true),
let (element, is_const, is_direct, value_needs_ref) = match inner {
OptionInner::RustBox(key) => (RustOption::RustBox(key.rust), false, false, true),
OptionInner::Ref(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::Ref(key.rust), true, false)
(RustOption::Ref(key.rust), true, false, false)
}
OptionInner::MutRef(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::MutRef(key.rust), false, false)
(RustOption::MutRef(key.rust), false, false, false)
}
OptionInner::RefVec(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::RefVec(key.rust), true, false)
(RustOption::RefVec(key.rust), true, false, false)
}
OptionInner::MutRefVec(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::MutRefVec(key.rust), false, false)
(RustOption::MutRefVec(key.rust), false, false, false)
}
OptionInner::Vec(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::Vec(key.rust), false, true, true)
}
OptionInner::Ident(key) => {
if out.types.try_resolve(key.rust).is_none() {
return;
}
(RustOption::Ident(key.rust), false, true, true)
}
};
let inner = element.to_typename(out.types);
Expand Down Expand Up @@ -1897,11 +2010,19 @@ fn write_rust_option_impl(out: &mut OutFile, inner: OptionInner) {
writeln!(out, "template <>");
begin_function_definition(out);
writeln!(out, "void Option<{0}>::set({0} value) noexcept {{", inner);
writeln!(
out,
" return cxxbridge1$rust_option${}$set(this, &value);",
instance
);
if is_direct {
writeln!(
out,
" return cxxbridge1$rust_option${}$set(this, value);",
instance
);
} else {
writeln!(
out,
" return cxxbridge1$rust_option${}$set(this, &value);",
instance
);
}
writeln!(out, "}}");
}

Expand Down
Loading

0 comments on commit 70610dc

Please sign in to comment.