result.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <new>
  6. #include <utility>
  7. #include "common/assert.h"
  8. #include "common/bit_field.h"
  9. #include "common/common_funcs.h"
  10. #include "common/common_types.h"
  11. // All the constants in this file come from http://switchbrew.org/index.php?title=Error_codes
  12. /**
  13. * Detailed description of the error. Code 0 always means success.
  14. */
  15. enum class ErrorDescription : u32 {
  16. Success = 0,
  17. RemoteProcessDead = 301,
  18. InvalidOffset = 6061,
  19. InvalidLength = 6062,
  20. };
  21. /**
  22. * Identifies the module which caused the error. Error codes can be propagated through a call
  23. * chain, meaning that this doesn't always correspond to the module where the API call made is
  24. * contained.
  25. */
  26. enum class ErrorModule : u32 {
  27. Common = 0,
  28. Kernel = 1,
  29. FS = 2,
  30. NvidiaTransferMemory = 3,
  31. NCM = 5,
  32. DD = 6,
  33. LR = 8,
  34. Loader = 9,
  35. CMIF = 10,
  36. HIPC = 11,
  37. PM = 15,
  38. NS = 16,
  39. HTC = 18,
  40. SM = 21,
  41. RO = 22,
  42. SDMMC = 24,
  43. SPL = 26,
  44. ETHC = 100,
  45. I2C = 101,
  46. Settings = 105,
  47. NIFM = 110,
  48. Display = 114,
  49. NTC = 116,
  50. FGM = 117,
  51. PCIE = 120,
  52. Friends = 121,
  53. SSL = 123,
  54. Account = 124,
  55. Mii = 126,
  56. AM = 128,
  57. PlayReport = 129,
  58. PCV = 133,
  59. OMM = 134,
  60. NIM = 137,
  61. PSC = 138,
  62. USB = 140,
  63. BTM = 143,
  64. ERPT = 147,
  65. APM = 148,
  66. NPNS = 154,
  67. ARP = 157,
  68. BOOT = 158,
  69. NFC = 161,
  70. UserlandAssert = 162,
  71. UserlandCrash = 168,
  72. HID = 203,
  73. Capture = 206,
  74. TC = 651,
  75. GeneralWebApplet = 800,
  76. WifiWebAuthApplet = 809,
  77. WhitelistedApplet = 810,
  78. ShopN = 811,
  79. };
  80. /// Encapsulates a CTR-OS error code, allowing it to be separated into its constituent fields.
  81. union ResultCode {
  82. u32 raw;
  83. BitField<0, 9, ErrorModule> module;
  84. BitField<9, 13, u32> description;
  85. // The last bit of `level` is checked by apps and the kernel to determine if a result code is an
  86. // error
  87. BitField<31, 1, u32> is_error;
  88. constexpr explicit ResultCode(u32 raw) : raw(raw) {}
  89. constexpr ResultCode(ErrorModule module, ErrorDescription description)
  90. : ResultCode(module, static_cast<u32>(description)) {}
  91. constexpr ResultCode(ErrorModule module_, u32 description_)
  92. : raw(module.FormatValue(module_) | description.FormatValue(description_)) {}
  93. constexpr ResultCode& operator=(const ResultCode& o) {
  94. raw = o.raw;
  95. return *this;
  96. }
  97. constexpr bool IsSuccess() const {
  98. return is_error.ExtractValue(raw) == 0;
  99. }
  100. constexpr bool IsError() const {
  101. return is_error.ExtractValue(raw) == 1;
  102. }
  103. };
  104. constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
  105. return a.raw == b.raw;
  106. }
  107. constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
  108. return a.raw != b.raw;
  109. }
  110. // Convenience functions for creating some common kinds of errors:
  111. /// The default success `ResultCode`.
  112. constexpr ResultCode RESULT_SUCCESS(0);
  113. /**
  114. * This is an optional value type. It holds a `ResultCode` and, if that code is a success code,
  115. * also holds a result of type `T`. If the code is an error code then trying to access the inner
  116. * value fails, thus ensuring that the ResultCode of functions is always checked properly before
  117. * their return value is used. It is similar in concept to the `std::optional` type
  118. * (http://en.cppreference.com/w/cpp/experimental/optional) originally proposed for inclusion in
  119. * C++14, or the `Result` type in Rust (http://doc.rust-lang.org/std/result/index.html).
  120. *
  121. * An example of how it could be used:
  122. * \code
  123. * ResultVal<int> Frobnicate(float strength) {
  124. * if (strength < 0.f || strength > 1.0f) {
  125. * // Can't frobnicate too weakly or too strongly
  126. * return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Common,
  127. * ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
  128. * } else {
  129. * // Frobnicated! Give caller a cookie
  130. * return MakeResult<int>(42);
  131. * }
  132. * }
  133. * \endcode
  134. *
  135. * \code
  136. * ResultVal<int> frob_result = Frobnicate(0.75f);
  137. * if (frob_result) {
  138. * // Frobbed ok
  139. * printf("My cookie is %d\n", *frob_result);
  140. * } else {
  141. * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.code().hex);
  142. * }
  143. * \endcode
  144. */
  145. template <typename T>
  146. class ResultVal {
  147. public:
  148. /// Constructs an empty `ResultVal` with the given error code. The code must not be a success
  149. /// code.
  150. ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) {
  151. ASSERT(error_code.IsError());
  152. }
  153. /**
  154. * Similar to the non-member function `MakeResult`, with the exception that you can manually
  155. * specify the success code. `success_code` must not be an error code.
  156. */
  157. template <typename... Args>
  158. static ResultVal WithCode(ResultCode success_code, Args&&... args) {
  159. ResultVal<T> result;
  160. result.emplace(success_code, std::forward<Args>(args)...);
  161. return result;
  162. }
  163. ResultVal(const ResultVal& o) : result_code(o.result_code) {
  164. if (!o.empty()) {
  165. new (&object) T(o.object);
  166. }
  167. }
  168. ResultVal(ResultVal&& o) : result_code(o.result_code) {
  169. if (!o.empty()) {
  170. new (&object) T(std::move(o.object));
  171. }
  172. }
  173. ~ResultVal() {
  174. if (!empty()) {
  175. object.~T();
  176. }
  177. }
  178. ResultVal& operator=(const ResultVal& o) {
  179. if (!empty()) {
  180. if (!o.empty()) {
  181. object = o.object;
  182. } else {
  183. object.~T();
  184. }
  185. } else {
  186. if (!o.empty()) {
  187. new (&object) T(o.object);
  188. }
  189. }
  190. result_code = o.result_code;
  191. return *this;
  192. }
  193. /**
  194. * Replaces the current result with a new constructed result value in-place. The code must not
  195. * be an error code.
  196. */
  197. template <typename... Args>
  198. void emplace(ResultCode success_code, Args&&... args) {
  199. ASSERT(success_code.IsSuccess());
  200. if (!empty()) {
  201. object.~T();
  202. }
  203. new (&object) T(std::forward<Args>(args)...);
  204. result_code = success_code;
  205. }
  206. /// Returns true if the `ResultVal` contains an error code and no value.
  207. bool empty() const {
  208. return result_code.IsError();
  209. }
  210. /// Returns true if the `ResultVal` contains a return value.
  211. bool Succeeded() const {
  212. return result_code.IsSuccess();
  213. }
  214. /// Returns true if the `ResultVal` contains an error code and no value.
  215. bool Failed() const {
  216. return empty();
  217. }
  218. ResultCode Code() const {
  219. return result_code;
  220. }
  221. const T& operator*() const {
  222. return object;
  223. }
  224. T& operator*() {
  225. return object;
  226. }
  227. const T* operator->() const {
  228. return &object;
  229. }
  230. T* operator->() {
  231. return &object;
  232. }
  233. /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
  234. template <typename U>
  235. T ValueOr(U&& value) const {
  236. return !empty() ? object : std::move(value);
  237. }
  238. /// Asserts that the result succeeded and returns a reference to it.
  239. T& Unwrap() & {
  240. ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
  241. return **this;
  242. }
  243. T&& Unwrap() && {
  244. ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
  245. return std::move(**this);
  246. }
  247. private:
  248. // A union is used to allocate the storage for the value, while allowing us to construct and
  249. // destruct it at will.
  250. union {
  251. T object;
  252. };
  253. ResultCode result_code;
  254. };
  255. /**
  256. * This function is a helper used to construct `ResultVal`s. It receives the arguments to construct
  257. * `T` with and creates a success `ResultVal` contained the constructed value.
  258. */
  259. template <typename T, typename... Args>
  260. ResultVal<T> MakeResult(Args&&... args) {
  261. return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...);
  262. }
  263. /**
  264. * Deducible overload of MakeResult, allowing the template parameter to be ommited if you're just
  265. * copy or move constructing.
  266. */
  267. template <typename Arg>
  268. ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
  269. return ResultVal<std::remove_reference_t<Arg>>::WithCode(RESULT_SUCCESS,
  270. std::forward<Arg>(arg));
  271. }
  272. /**
  273. * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps
  274. * the contained value and assigns it to `target`, which can be either an l-value expression or a
  275. * variable declaration. If it fails the return code is returned from the current function. Thus it
  276. * can be used to cascade errors out, achieving something akin to exception handling.
  277. */
  278. #define CASCADE_RESULT(target, source) \
  279. auto CONCAT2(check_result_L, __LINE__) = source; \
  280. if (CONCAT2(check_result_L, __LINE__).Failed()) \
  281. return CONCAT2(check_result_L, __LINE__).Code(); \
  282. target = std::move(*CONCAT2(check_result_L, __LINE__))
  283. /**
  284. * Analogous to CASCADE_RESULT, but for a bare ResultCode. The code will be propagated if
  285. * non-success, or discarded otherwise.
  286. */
  287. #define CASCADE_CODE(source) \
  288. auto CONCAT2(check_result_L, __LINE__) = source; \
  289. if (CONCAT2(check_result_L, __LINE__).IsError()) \
  290. return CONCAT2(check_result_L, __LINE__);