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