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