Skip to content

Commit 06f80db

Browse files
committed
rust error callback
Rather then throw things directly, introduce a global callback. We will override the callback in workerd to integrate with kj::Exception
1 parent a6804d6 commit 06f80db

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

gen/src/builtin.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,11 @@ pub(super) fn write(out: &mut OutFile) {
350350
writeln!(out, "template <>");
351351
writeln!(out, "class impl<Error> final {{");
352352
writeln!(out, "public:");
353-
writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
353+
writeln!(out, " static void error(const char* msg, size_t len) {{");
354354
writeln!(out, " Error error;");
355-
writeln!(out, " error.msg = static_cast<char const *>(repr.ptr);");
356-
writeln!(out, " error.len = repr.len;");
357-
writeln!(out, " return error;");
355+
writeln!(out, " error.msg = msg;");
356+
writeln!(out, " error.len = len;");
357+
writeln!(out, " throw error;");
358358
writeln!(out, " }}");
359359
writeln!(out, "}};");
360360
}
@@ -393,6 +393,15 @@ pub(super) fn write(out: &mut OutFile) {
393393
}
394394

395395
out.end_block(Block::AnonymousNamespace);
396+
397+
if builtin.rust_error {
398+
out.next_section();
399+
writeln!(
400+
out,
401+
"void (*throw_rust_error)(const char*, size_t) = impl<Error>::error;"
402+
);
403+
}
404+
396405
out.end_block(Block::InlineNamespace("cxxbridge1"));
397406

398407
if builtin.trycatch {

gen/src/write.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,10 @@ fn write_rust_function_shim_impl(
11231123
if sig.throws {
11241124
out.builtin.rust_error = true;
11251125
writeln!(out, " if (error$.ptr) {{");
1126-
writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
1126+
writeln!(
1127+
out,
1128+
" ::rust::throw_rust_error(static_cast<char const *>(error$.ptr), error$.len);"
1129+
);
11271130
writeln!(out, " }}");
11281131
}
11291132
if indirect_return {

include/cxx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ template <typename T>
3030
class impl;
3131
}
3232

33+
extern void (*throw_rust_error)(const char*, size_t);
34+
3335
#ifndef CXXBRIDGE1_RUST_STRING
3436
#define CXXBRIDGE1_RUST_STRING
3537
// https://cxx.rs/binding/string.html

tests/ffi/tests.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "tests/ffi/lib.rs.h"
33
#include <cstdlib>
44
#include <cstring>
5+
#include <exception>
56
#include <iterator>
67
#include <memory>
78
#include <numeric>
@@ -757,6 +758,20 @@ std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
757758
return f;
758759
}
759760

761+
struct TestException : public std::exception {
762+
TestException(std::string&& msg) : message(std::move(msg)) {}
763+
764+
static void do_throw(const char* msg, size_t len) {
765+
throw TestException(std::string(msg, len));
766+
}
767+
768+
const char* what() const noexcept override {
769+
return message.c_str();
770+
}
771+
772+
std::string message;
773+
};
774+
760775
extern "C" const char *cxx_run_test() noexcept {
761776
#define STRINGIFY(x) #x
762777
#define TOSTRING(x) STRINGIFY(x)
@@ -904,6 +919,15 @@ extern "C" const char *cxx_run_test() noexcept {
904919
(void)rust::Vec<size_t>();
905920
(void)rust::Vec<rust::isize>();
906921

922+
// Test custom exception handler
923+
::rust::throw_rust_error = TestException::do_throw;
924+
try {
925+
r_fail_return_primitive();
926+
ASSERT(false);
927+
} catch (const TestException &e) {
928+
ASSERT(std::strcmp(e.what(), "rust error") == 0);
929+
}
930+
907931
cxx_test_suite_set_correct();
908932
return nullptr;
909933
}

0 commit comments

Comments
 (0)