Skip to content

Commit 5bc06cc

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 0335ebf commit 5bc06cc

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

gen/src/builtin.rs

+13-4
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+
"inline 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

+4-1
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,10 @@ fn write_rust_function_shim_impl(
11031103
writeln!(out, ";");
11041104
out.builtin.rust_error = true;
11051105
writeln!(out, " if (error$.ptr) {{");
1106-
writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
1106+
writeln!(
1107+
out,
1108+
" ::rust::throw_rust_error(static_cast<char const *>(error$.ptr), error$.len);"
1109+
);
11071110
writeln!(out, " }}");
11081111

11091112
if indirect_return {

include/cxx.h

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ template <typename T>
3030
class impl;
3131
}
3232

33+
// msg is 0-terminated, size counts the 0.
34+
// msg was new char[] allocated, ownership is transferred to throw_rust_error.
35+
extern void (*throw_rust_error)(const char* msg, size_t size);
36+
3337
#ifndef CXXBRIDGE1_RUST_STRING
3438
#define CXXBRIDGE1_RUST_STRING
3539
// https://cxx.rs/binding/string.html

tests/ffi/tests.cc

+26
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)
@@ -911,6 +926,17 @@ extern "C" const char *cxx_run_test() noexcept {
911926
ASSERT(std::strcmp(e.what(), "panic in cxx_test_suite::ffi::r_panic: foobar") == 0);
912927
}
913928

929+
// Test custom exception handler
930+
auto prev_handler = ::rust::throw_rust_error;
931+
::rust::throw_rust_error = TestException::do_throw;
932+
try {
933+
r_fail_return_primitive();
934+
ASSERT(false);
935+
} catch (const TestException &e) {
936+
ASSERT(std::strcmp(e.what(), "rust error") == 0);
937+
}
938+
::rust::throw_rust_error = prev_handler;
939+
914940
cxx_test_suite_set_correct();
915941
return nullptr;
916942
}

0 commit comments

Comments
 (0)