1 /** 2 * \file wasmtime/error.hh 3 */ 4 5 #ifndef WASMTIME_ERROR_HH 6 #define WASMTIME_ERROR_HH 7 8 #include <memory> 9 #include <optional> 10 #include <string> 11 #include <variant> 12 #include <wasmtime/error.h> 13 14 namespace wasmtime { 15 16 class Trace; 17 18 /** 19 * \brief Errors coming from Wasmtime 20 * 21 * This class represents an error that came from Wasmtime and contains a textual 22 * description of the error that occurred. 23 */ 24 class Error { 25 struct deleter { 26 void operator()(wasmtime_error_t *p) const { wasmtime_error_delete(p); } 27 }; 28 29 std::unique_ptr<wasmtime_error_t, deleter> ptr; 30 31 public: 32 /// \brief Creates an error from the raw C API representation 33 /// 34 /// Takes ownership of the provided `error`. 35 Error(wasmtime_error_t *error) : ptr(error) {} 36 37 /// \brief Creates an error with the provided message. 38 Error(const std::string &s) : ptr(wasmtime_error_new(s.c_str())) {} 39 40 /// \brief Returns the error message associated with this error. 41 std::string message() const { 42 wasm_byte_vec_t msg_bytes; 43 wasmtime_error_message(ptr.get(), &msg_bytes); 44 auto ret = std::string(msg_bytes.data, msg_bytes.size); 45 wasm_byte_vec_delete(&msg_bytes); 46 return ret; 47 } 48 49 /// If this trap represents a call to `exit` for WASI, this will return the 50 /// optional error code associated with the exit trap. 51 std::optional<int32_t> i32_exit() const { 52 int32_t status = 0; 53 if (wasmtime_error_exit_status(ptr.get(), &status)) { 54 return status; 55 } 56 return std::nullopt; 57 } 58 59 /// Returns the trace of WebAssembly frames associated with this error. 60 /// 61 /// Note that the `trace` cannot outlive this error object. 62 Trace trace() const; 63 64 /// Release ownership of this error, acquiring the underlying C raw pointer. 65 wasmtime_error_t *release() { return ptr.release(); } 66 }; 67 68 /// \brief Used to print an error. 69 inline std::ostream &operator<<(std::ostream &os, const Error &e) { 70 os << e.message(); 71 return os; 72 } 73 74 /** 75 * \brief Fallible result type used for Wasmtime. 76 * 77 * This type is used as the return value of many methods in the Wasmtime API. 78 * This behaves similarly to Rust's `Result<T, E>` and will be replaced with a 79 * C++ standard when it exists. 80 */ 81 template <typename T, typename E = Error> class [[nodiscard]] Result { 82 std::variant<T, E> data; 83 84 public: 85 /// \brief Creates a `Result` from its successful value. 86 Result(T t) : data(std::move(t)) {} 87 /// \brief Creates a `Result` from an error value. 88 Result(E e) : data(std::move(e)) {} 89 90 /// \brief Returns `true` if this result is a success, `false` if it's an 91 /// error 92 explicit operator bool() const { return data.index() == 0; } 93 94 /// \brief Returns the error, if present, aborts if this is not an error. 95 E &&err() { return std::get<E>(std::move(data)); } 96 /// \brief Returns the error, if present, aborts if this is not an error. 97 const E &&err() const { return std::get<E>(std::move(data)); } 98 99 /// \brief Returns the success, if present, aborts if this is an error. 100 T &&ok() { return std::get<T>(std::move(data)); } 101 /// \brief Returns the success, if present, aborts if this is an error. 102 const T &&ok() const { return std::get<T>(std::move(data)); } 103 104 /// \brief Returns the success, if present, aborts if this is an error. 105 T unwrap() { 106 if (*this) { 107 return this->ok(); 108 } 109 unwrap_failed(); 110 } 111 112 private: 113 [[noreturn]] void unwrap_failed() { 114 fprintf(stderr, "error: %s\n", this->err().message().c_str()); // NOLINT 115 std::abort(); 116 } 117 }; 118 119 } // namespace wasmtime 120 121 #endif // WASMTIME_ERROR_HH 122