You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

error.hxx 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright 2024 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef RSPAMD_ERROR_HXX
  17. #define RSPAMD_ERROR_HXX
  18. #pragma once
  19. #include "config.h"
  20. #include <string>
  21. #include <string_view>
  22. #include <cstdint>
  23. #include <optional>
  24. /***
  25. * This unit is used to represent Rspamd C++ errors in a way to interoperate
  26. * with C code if needed and avoid allocations for static strings
  27. */
  28. namespace rspamd::util {
  29. enum class error_category : std::uint8_t {
  30. INFORMAL,
  31. IMPORTANT,
  32. CRITICAL
  33. };
  34. struct error {
  35. public:
  36. /**
  37. * Construct from a static string, this string must live long enough to outlive this object
  38. * @param msg
  39. * @param code
  40. * @param category
  41. */
  42. error(const char *msg, int code, error_category category = error_category::INFORMAL)
  43. : error_message(msg), error_code(code), category(category)
  44. {
  45. }
  46. /**
  47. * Construct error from a temporary string taking membership
  48. * @param msg
  49. * @param code
  50. * @param category
  51. */
  52. error(std::string &&msg, int code, error_category category = error_category::INFORMAL)
  53. : error_code(code), category(category)
  54. {
  55. static_storage = std::move(msg);
  56. error_message = static_storage.value();
  57. }
  58. /**
  59. * Construct error from another string copying it into own storage
  60. * @param msg
  61. * @param code
  62. * @param category
  63. */
  64. error(const std::string &msg, int code, error_category category = error_category::INFORMAL)
  65. : error_code(code), category(category)
  66. {
  67. static_storage = msg;
  68. error_message = static_storage.value();
  69. }
  70. error(const error &other)
  71. : error_code(other.error_code), category(other.category)
  72. {
  73. if (other.static_storage) {
  74. static_storage = other.static_storage;
  75. error_message = static_storage.value();
  76. }
  77. else {
  78. error_message = other.error_message;
  79. }
  80. }
  81. error(error &&other) noexcept
  82. {
  83. *this = std::move(other);
  84. }
  85. error &operator=(error &&other) noexcept
  86. {
  87. if (other.static_storage.has_value()) {
  88. std::swap(static_storage, other.static_storage);
  89. error_message = static_storage.value();
  90. }
  91. else {
  92. std::swap(error_message, other.error_message);
  93. }
  94. std::swap(other.error_code, error_code);
  95. std::swap(other.category, category);
  96. return *this;
  97. }
  98. /**
  99. * Convert into GError
  100. * @return
  101. */
  102. auto into_g_error() const -> GError *
  103. {
  104. return g_error_new(g_quark_from_static_string("rspamd"), error_code, "%s",
  105. error_message.data());
  106. }
  107. /**
  108. * Convenience alias for the `into_g_error`
  109. * @param err
  110. */
  111. auto into_g_error_set(GError **err) const -> void
  112. {
  113. if (err && *err == nullptr) {
  114. *err = into_g_error();
  115. }
  116. }
  117. /**
  118. * Convert into GError
  119. * @return
  120. */
  121. auto into_g_error(GQuark quark) const -> GError *
  122. {
  123. return g_error_new(quark, error_code, "%s",
  124. error_message.data());
  125. }
  126. /**
  127. * Convenience alias for the `into_g_error`
  128. * @param err
  129. */
  130. auto into_g_error_set(GQuark quark, GError **err) const -> void
  131. {
  132. if (err && *err == nullptr) {
  133. *err = into_g_error(quark);
  134. }
  135. }
  136. public:
  137. std::string_view error_message;
  138. int error_code;
  139. error_category category;
  140. private:
  141. std::optional<std::string> static_storage;
  142. };
  143. }// namespace rspamd::util
  144. #endif//RSPAMD_ERROR_HXX