result.h 10 KB

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