#pragma once
#include <new>
#include <utility>
#include "executorch/runtime/core/error.h"
#include "executorch/runtime/platform/assert.h"
namespace executorch {
namespace runtime {
template <typename T>
class Result final {
public:
typedef T value_type;
Result(Error error)
: error_(error == Error::Ok ? Error::Internal : error), hasValue_(false) {
if ET_UNLIKELY (error == Error::Ok) {
ET_LOG(
Debug,
"Attempted to create Result from Error::Ok, this has been converted to Error::Internal.");
}
}
Result(const T& val) : value_(val), hasValue_(true) {}
Result(T&& val) : value_(std::move(val)), hasValue_(true) {}
Result(Result&& rhs) noexcept : hasValue_(rhs.hasValue_) {
if (hasValue_) {
new (&value_) T(std::move(rhs.value_));
} else {
error_ = rhs.error_;
}
}
~Result() {
if (hasValue_) {
value_.~T();
}
}
ET_NODISCARD bool ok() const {
return hasValue_;
}
ET_NODISCARD Error error() const {
if (hasValue_) {
return Error::Ok;
} else {
return error_;
}
}
T& get() {
CheckOk();
return value_;
}
const T& get() const {
CheckOk();
return value_;
}
const T& operator*() const&;
T& operator*() &;
const T* operator->() const;
T* operator->();
private:
Result() = delete;
Result(const Result&) = delete;
Result& operator=(const Result&) = delete;
Result& operator=(Result&& rhs) = delete;
void CheckOk() const {
ET_CHECK(hasValue_);
}
union {
T value_; Error error_; };
const bool hasValue_;
};
template <typename T>
const T& Result<T>::operator*() const& {
CheckOk();
return value_;
}
template <typename T>
T& Result<T>::operator*() & {
CheckOk();
return value_;
}
template <typename T>
const T* Result<T>::operator->() const {
CheckOk();
return &value_;
}
template <typename T>
T* Result<T>::operator->() {
CheckOk();
return &value_;
}
} }
namespace torch {
namespace executor {
using ::executorch::runtime::Result;
} }
#define ET_UNWRAP(result__, ...) ET_INTERNAL_UNWRAP(result__, ##__VA_ARGS__)
#define ET_INTERNAL_UNWRAP(...) \
ET_INTERNAL_UNWRAP_SELECT(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) \
(__VA_ARGS__)
#define ET_INTERNAL_UNWRAP_SELECT( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) \
ET_INTERNAL_UNWRAP_##N
#define ET_INTERNAL_UNWRAP_1(result__) \
({ \
auto et_result__ = (result__); \
if (!et_result__.ok()) { \
return et_result__.error(); \
} \
std::move(*et_result__); \
})
#define ET_INTERNAL_UNWRAP_2(result__, message__, ...) \
({ \
auto et_result__ = (result__); \
if (!et_result__.ok()) { \
ET_LOG(Error, message__, ##__VA_ARGS__); \
return et_result__.error(); \
} \
std::move(*et_result__); \
})
#define ET_INTERNAL_UNWRAP_3 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_4 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_5 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_6 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_7 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_8 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_9 ET_INTERNAL_UNWRAP_2
#define ET_INTERNAL_UNWRAP_10 ET_INTERNAL_UNWRAP_2
#define ET_ASSIGN_OR_RETURN(...) \
ET_INTERNAL_ASSIGN_OR_RETURN_EXPAND(ET_INTERNAL_ASSIGN_OR_RETURN_SELECT( \
__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)(__VA_ARGS__))
#define ET_INTERNAL_ASSIGN_OR_RETURN_EXPAND(x) x
#define ET_INTERNAL_ASSIGN_OR_RETURN_SELECT( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, ...) \
ET_INTERNAL_ASSIGN_OR_RETURN_##N
#define ET_INTERNAL_ASSIGN_OR_RETURN_2(var__, result__) \
auto et_assign_result_##var__ = (result__); \
if (!et_assign_result_##var__.ok()) { \
return et_assign_result_##var__.error(); \
} \
auto var__ = std::move(*et_assign_result_##var__)
#define ET_INTERNAL_ASSIGN_OR_RETURN_3(var__, result__, message__, ...) \
auto et_assign_result_##var__ = (result__); \
if (!et_assign_result_##var__.ok()) { \
ET_LOG(Error, message__, ##__VA_ARGS__); \
return et_assign_result_##var__.error(); \
} \
auto var__ = std::move(*et_assign_result_##var__)
#define ET_INTERNAL_ASSIGN_OR_RETURN_4 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_5 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_6 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_7 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_8 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_9 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_10 ET_INTERNAL_ASSIGN_OR_RETURN_3
#define ET_INTERNAL_ASSIGN_OR_RETURN_11 ET_INTERNAL_ASSIGN_OR_RETURN_3