result.h 10 KB

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