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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 "libutil/cxx/string.hxx"
  21. #include <cstdint>
  22. #include <optional>
  23. /***
  24. * This unit is used to represent Rspamd C++ errors in a way to interoperate
  25. * with C code if needed and avoid allocations for static strings
  26. */
  27. namespace rspamd::util {
  28. enum class error_category : std::uint8_t {
  29. INFORMAL,
  30. IMPORTANT,
  31. CRITICAL
  32. };
  33. struct error {
  34. public:
  35. /**
  36. * Construct from a static string, this string must live long enough to outlive this object
  37. * @param msg
  38. * @param code
  39. * @param category
  40. */
  41. error(const char *msg, int code, error_category category = error_category::INFORMAL)
  42. : error_message(msg), error_code(code), category(category)
  43. {
  44. }
  45. /**
  46. * Construct error from a temporary string taking membership
  47. * @param msg
  48. * @param code
  49. * @param category
  50. */
  51. error(sz::string &&msg, int code, error_category category = error_category::INFORMAL)
  52. : error_code(code), category(category)
  53. {
  54. static_storage = std::move(msg);
  55. error_message = static_storage.value();
  56. }
  57. /**
  58. * Construct error from another string copying it into own storage
  59. * @param msg
  60. * @param code
  61. * @param category
  62. */
  63. error(const sz::string &msg, int code, error_category category = error_category::INFORMAL)
  64. : error_code(code), category(category)
  65. {
  66. static_storage = msg;
  67. error_message = static_storage.value();
  68. }
  69. error(const error &other)
  70. : error_code(other.error_code), category(other.category)
  71. {
  72. if (other.static_storage) {
  73. static_storage = other.static_storage;
  74. error_message = static_storage.value();
  75. }
  76. else {
  77. error_message = other.error_message;
  78. }
  79. }
  80. error(error &&other) noexcept
  81. {
  82. *this = std::move(other);
  83. }
  84. error &operator=(error &&other) noexcept
  85. {
  86. if (other.static_storage.has_value()) {
  87. std::swap(static_storage, other.static_storage);
  88. error_message = static_storage.value();
  89. }
  90. else {
  91. std::swap(error_message, other.error_message);
  92. }
  93. std::swap(other.error_code, error_code);
  94. std::swap(other.category, category);
  95. return *this;
  96. }
  97. /**
  98. * Convert into GError
  99. * @return
  100. */
  101. auto into_g_error() const -> GError *
  102. {
  103. return g_error_new(g_quark_from_static_string("rspamd"), error_code, "%s",
  104. error_message.data());
  105. }
  106. /**
  107. * Convenience alias for the `into_g_error`
  108. * @param err
  109. */
  110. auto into_g_error_set(GError **err) const -> void
  111. {
  112. if (err && *err == nullptr) {
  113. *err = into_g_error();
  114. }
  115. }
  116. /**
  117. * Convert into GError
  118. * @return
  119. */
  120. auto into_g_error(GQuark quark) const -> GError *
  121. {
  122. return g_error_new(quark, error_code, "%s",
  123. error_message.data());
  124. }
  125. /**
  126. * Convenience alias for the `into_g_error`
  127. * @param err
  128. */
  129. auto into_g_error_set(GQuark quark, GError **err) const -> void
  130. {
  131. if (err && *err == nullptr) {
  132. *err = into_g_error(quark);
  133. }
  134. }
  135. public:
  136. sz::string_view error_message;
  137. int error_code;
  138. error_category category;
  139. private:
  140. std::optional<sz::string> static_storage;
  141. };
  142. }// namespace rspamd::util
  143. #endif//RSPAMD_ERROR_HXX