Serenity Operating System
1/*
2 * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/DeprecatedFlyString.h>
10#include <AK/Error.h>
11#include <errno.h>
12
13namespace Audio {
14
15struct LoaderError {
16
17 enum class Category : u32 {
18 // The error category is unknown.
19 Unknown = 0,
20 IO,
21 // The read file doesn't follow the file format.
22 Format,
23 // Equivalent to an ASSERT(), except non-crashing.
24 Internal,
25 // The loader encountered something in the format that is not yet implemented.
26 Unimplemented,
27 };
28 Category category { Category::Unknown };
29 // Binary index: where in the file the error occurred.
30 size_t index { 0 };
31 DeprecatedFlyString description { DeprecatedString::empty() };
32
33 constexpr LoaderError() = default;
34 LoaderError(Category category, size_t index, DeprecatedFlyString description)
35 : category(category)
36 , index(index)
37 , description(move(description))
38 {
39 }
40 LoaderError(DeprecatedFlyString description)
41 : description(move(description))
42 {
43 }
44 LoaderError(Category category, DeprecatedFlyString description)
45 : category(category)
46 , description(move(description))
47 {
48 }
49
50 LoaderError(LoaderError&) = default;
51 LoaderError(LoaderError&&) = default;
52
53 LoaderError(Error&& error)
54 {
55 if (error.is_errno()) {
56 auto code = error.code();
57 description = DeprecatedString::formatted("{} ({})", strerror(code), code);
58 if (code == EBADF || code == EBUSY || code == EEXIST || code == EIO || code == EISDIR || code == ENOENT || code == ENOMEM || code == EPIPE)
59 category = Category::IO;
60 } else {
61 description = error.string_literal();
62 }
63 }
64};
65
66}
67
68// Convenience TRY-like macro to convert an Error to a LoaderError
69#define LOADER_TRY(expression) \
70 ({ \
71 auto&& _temporary_result = (expression); \
72 if (_temporary_result.is_error()) \
73 return LoaderError(_temporary_result.release_error()); \
74 static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
75 "Do not return a reference from a fallible expression"); \
76 _temporary_result.release_value(); \
77 })