Enrollment 28.2.0
Loading...
Searching...
No Matches
CallbackError.h
Go to the documentation of this file.
1
10
11#pragma once
19#include <optional>
20#include <variant>
21
22namespace inno
23{
24 /*
25 * @ingroup g_Exception
26 * @brief Type of error from binary implementation of enrollment-sdk
27 */
28 enum class CallbackErrorType : uint8_t
29 {
30 RUNTIME,
31 INVALID_ARGUMENT,
32 INVALID_ARGUMENT_BLANK_TEMPLATE,
33 INVALID_ARGUMENT_UNSUPPORTED_TEMPLATE,
34 INVALID_ARGUMENT_INCOMPATIBLE_TEMPLATE,
35 INVALID_ARGUMENT_IMAGE,
36 INVALID_ARGUMENT_NULL,
37 LICENSE,
38 LICENSE_NOT_FOUND,
39 LICENSE_INVALID,
40 LICENSE_EXPIRED,
41 LICENSE_FEATURE_NOT_ALLOWED,
42 LICENSE_INVALID_HWID,
43 LICENSE_LIMIT_REACHED,
44 NOT_SUPPORTED,
45 FILE,
46 IMAGE_DECODE,
47 IMAGE_ENCODE,
48 IMAGE_PROCESS,
49 IMAGE_UNKNOWN
50 };
51
52 /*
53 * @ingroup g_Exception
54 * @brief Function pointer to save message and exception type.
55 * @param type exception type
56 * @param description error description
57 * @param file location
58 * @param line location
59 * @param function location
60 * @param object pointer to object that provides this call back
61 * @note Only for C++
62 */
63 using ErrorCallback = void (*)(CallbackErrorType type,
64 const char* description,
65 const char* file,
66 const char* function,
67 int line,
68 void* object);
69
70 // See doc/Main.markdown "Header and Binary parts" for reason why we use pragma pack 1
71#pragma pack(push, 1)
72 /*
73 * @ingroup g_Exception
74 * @brief ErrorCallback's contains exception handle and function pointer as callback.
75 * @note Only for C++
76 */
77 extern "C" struct ErrorCallbacks
78 {
79 // Exception handle. It is not used in binary. Binary provides this handle back to header part of library, that
80 // cast it safely to already created Exception class.
81 void* object;
82 // Callback to store exception data
83 ErrorCallback setException;
84 };
85#pragma pack(pop)
86
87 /*
88 * @ingroup g_Exception
89 * @brief CallbackError is exception for binary part of libary due to @ref overview_design_hbp "C boundary".
90 * It provides static functions that can be called from binary part to log messages.
91 * @note Only for C++
92 */
93 class CallbackError
94 {
95 public:
96 /*
97 * @brief Get the CallbackError object
98 *
99 * @return ErrorCallbacks
100 */
101 [[nodiscard]] ErrorCallbacks GetCallbacks()
102 {
103 ErrorCallbacks cb = {};
104 cb.object = this;
105 cb.setException = &CallbackError::Set;
106 return cb;
107 }
108
109 /*
110 * @brief Set exception type and message for given CallbackError object
111 *
112 * @param type type of exception
113 * @param description exception description
114 * @param file location
115 * @param line location
116 * @param function location
117 * @param object pointer to CallbackError object
118 */
119 static void Set(CallbackErrorType t,
120 const char* description,
121 const char* file,
122 const char* function,
123 int line,
124 void* object)
125 {
126 if (object == nullptr)
127 {
128 return;
129 }
130 static_cast<CallbackError*>(object)->Set(t, description, SourceLocation{ file, function, line });
131 }
132
133 /*
134 * @brief Function will throw exception if set.
135 * It reset error to be not thrown again in destructor.
136 */
137 void ThrowOnError()
138 {
139 if (exception.has_value())
140 {
141 std::visit([](auto e) { throw e; }, exception.value());
142 }
143 }
144
145 /*
146 * @brief Function sets stored error if any via given callbacks.
147 */
148 void PropagateVia(ErrorCallbacks& cb) const
149 {
150 if (exception.has_value() && cb.setException != nullptr)
151 {
152 std::visit(
153 [&](auto&& e)
154 {
155 cb.setException(type.value(),
156 e.what(),
157 e.Location().FileName().c_str(),
158 e.Location().FunctionName().c_str(),
159 e.Location().Line(),
160 cb.object);
161 },
162 exception.value());
163 }
164 }
165
166 CallbackError(CallbackErrorType t, std::string d, const SourceLocation& loc = SourceLocation{})
167 {
168 Set(t, std::move(d), loc);
169 }
170
171 /*
172 * @return true when error occur
173 */
174 [[nodiscard]] bool IsError() const
175 {
176 return exception.has_value();
177 }
178
179 /*
180 * @return error message
181 */
182 [[nodiscard]] const char* What() const noexcept
183 {
184 try
185 {
186 if (exception.has_value())
187 {
188 return std::visit([](const auto& e) { return e.what(); }, exception.value());
189 }
190 }
191 catch (...)
192 {
193 return "Failed to get CallbackError description";
194 }
195 return "";
196 }
197
198 /*
199 * @return error type if any
200 */
201 [[nodiscard]] std::optional<CallbackErrorType> Type() const
202 {
203 return type;
204 }
205
206 CallbackError() = default;
207
208 private:
209 std::optional<std::variant<EnrollmentRuntimeException,
210 EnrollmentInvalidArgumentException,
211 LicenseException,
212 LicenseNotFoundException,
213 InvalidLicenseException,
214 ExpiredLicenseException,
215 LicenseFeatureNotAllowedException,
216 InvalidHWIDException,
217 LicenseLimitReachedException,
218 NotSupportedException,
219 InvalidTemplateException,
220 UnsupportedTemplateException,
221 FileException,
222 ImageException,
223 IncompatibleTemplateException,
224 InvalidImageArgumentException,
225 NullArgumentException>>
226 exception;
227 std::optional<CallbackErrorType> type;
228
229 void Set(CallbackErrorType t, std::string d, const SourceLocation& loc)
230 {
231 type = t;
232
233 switch (t)
234 {
235 case CallbackErrorType::RUNTIME:
236 exception.emplace(EnrollmentRuntimeException(std::move(d), loc));
237 return;
238 case CallbackErrorType::INVALID_ARGUMENT:
239 exception.emplace(EnrollmentInvalidArgumentException(std::move(d), loc));
240 return;
241 case CallbackErrorType::LICENSE:
242 exception.emplace(LicenseException(std::move(d), loc));
243 return;
244 case CallbackErrorType::LICENSE_NOT_FOUND:
245 exception.emplace(LicenseNotFoundException(std::move(d), loc));
246 return;
247 case CallbackErrorType::LICENSE_INVALID:
248 exception.emplace(InvalidLicenseException(std::move(d), loc));
249 return;
250 case CallbackErrorType::LICENSE_EXPIRED:
251 exception.emplace(ExpiredLicenseException(std::move(d), loc));
252 return;
253 case CallbackErrorType::LICENSE_FEATURE_NOT_ALLOWED:
254 exception.emplace(LicenseFeatureNotAllowedException(std::move(d), loc));
255 return;
256 case CallbackErrorType::LICENSE_INVALID_HWID:
257 exception.emplace(InvalidHWIDException(std::move(d), loc));
258 return;
259 case CallbackErrorType::LICENSE_LIMIT_REACHED:
260 exception.emplace(LicenseLimitReachedException(std::move(d), loc));
261 return;
262 case CallbackErrorType::NOT_SUPPORTED:
263 exception.emplace(NotSupportedException(std::move(d), loc));
264 return;
265 case CallbackErrorType::INVALID_ARGUMENT_BLANK_TEMPLATE:
266 exception.emplace(InvalidTemplateException(std::move(d), loc));
267 return;
268 case CallbackErrorType::INVALID_ARGUMENT_UNSUPPORTED_TEMPLATE:
269 exception.emplace(UnsupportedTemplateException(std::move(d), loc));
270 return;
271 case CallbackErrorType::FILE:
272 exception.emplace(FileException(std::move(d), loc));
273 return;
274 case CallbackErrorType::IMAGE_DECODE:
275 exception.emplace(ImageException(ImageException::Reason::DECODE_IMAGE, std::move(d), loc));
276 return;
277 case CallbackErrorType::IMAGE_ENCODE:
278 exception.emplace(ImageException(ImageException::Reason::ENCODE_IMAGE, std::move(d), loc));
279 return;
280 case CallbackErrorType::IMAGE_PROCESS:
281 exception.emplace(ImageException(ImageException::Reason::PROCESS_IMAGE, std::move(d), loc));
282 return;
283 case CallbackErrorType::IMAGE_UNKNOWN:
284 exception.emplace(ImageException(ImageException::Reason::UNKNOWN_IMAGE, std::move(d), loc));
285 return;
286 case CallbackErrorType::INVALID_ARGUMENT_INCOMPATIBLE_TEMPLATE:
287 exception.emplace(IncompatibleTemplateException(std::move(d), loc));
288 return;
289 case CallbackErrorType::INVALID_ARGUMENT_IMAGE:
290 exception.emplace(InvalidImageArgumentException(std::move(d), loc));
291 return;
292 case CallbackErrorType::INVALID_ARGUMENT_NULL:
293 exception.emplace(NullArgumentException(std::move(d), loc));
294 return;
295 }
296
297 // When value is not in enum, return runtime
298 std::string unknownMessage =
299 "Unknown error type '" + std::to_string(static_cast<unsigned int>(t)) + "', " + d;
300 exception = EnrollmentRuntimeException(std::move(unknownMessage), loc);
301 }
302 };
303
304 /*
305 * @ingroup g_Exception
306 * @brief ThrowOnError class automatically throws exception when error occur in binary part of SDK
307 * @note Only for C++
308 */
309 class ThrowOnError
310 {
311 public:
312 // Allow implicit conversion to ErrorCallbacks, enabling the use of ThrowOnError{} instead of explicitly calling
313 // ThrowOnError{}.GetCallbacks(). NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
314 operator ErrorCallbacks()
315 {
316 return error.GetCallbacks();
317 }
318 ThrowOnError() = default;
319 ~ThrowOnError() noexcept(false)
320 {
321 error.ThrowOnError();
322 }
323 ThrowOnError(const ThrowOnError&) = delete;
324 ThrowOnError(ThrowOnError&&) = delete;
325 ThrowOnError& operator=(const ThrowOnError&) = delete;
326 ThrowOnError& operator=(ThrowOnError&&) = delete;
327
328 private:
329 CallbackError error;
330 };
331
332 /*
333 * @ingroup g_Exception
334 * @brief It catches exception and transform them to callback calls
335 * @param errorCallbacks callbacks to be used to propagate exception
336 * @func function from which exceptions are caught and propagated
337 * @loc source location of this function call
338 * @note Only for C++
339 */
340 template<typename Func>
341 auto ForwardExceptionToCallbacks(ErrorCallbacks errorCallbacks,
342 Func&& func,
343 const SourceLocation& loc = SourceLocation{}) -> decltype(func())
344 {
345 using ReturnType = decltype(func());
346 try
347 {
348 if constexpr (std::is_void_v<ReturnType>)
349 {
350 std::forward<Func>(func)();
351 }
352 else
353 {
354 return std::forward<Func>(func)();
355 }
356 }
357 catch (const EnrollmentException& e)
358 {
359 CallbackError{ CallbackErrorType::RUNTIME, e.what(), e.Location() }.PropagateVia(errorCallbacks);
360 }
361 catch (std::exception& e)
362 {
363 CallbackError{ CallbackErrorType::RUNTIME, e.what(), loc }.PropagateVia(errorCallbacks);
364 }
365 catch (...)
366 {
367 CallbackError{ CallbackErrorType::RUNTIME, "Unknown error", loc }.PropagateVia(errorCallbacks);
368 }
369
370 if constexpr (!std::is_void_v<ReturnType>)
371 {
372 return ReturnType{};
373 }
374 }
375} // namespace inno
Base exception for all enrollment-sdk exceptions.
Definition EnrollmentException.h:26
const char * what() const noexcept override
Provides error message.
Definition EnrollmentException.h:49
SourceLocation Location() const noexcept
Provides location of error.
Definition EnrollmentException.h:58
@ ENCODE_IMAGE
Problem encode image to given format.
Definition ImageException.h:43
@ PROCESS_IMAGE
Problem to process an image.
Definition ImageException.h:47
@ DECODE_IMAGE
Image type is supported but image format is corrupted.
Definition ImageException.h:39
@ UNKNOWN_IMAGE
Image type is not supported.
Definition ImageException.h:35
Class to capture the source location of an error or exception.
Definition SourceLocation.h:25