result.h 10 KB

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