1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 06:58:11 +00:00
serenity/Userland/Libraries/LibVideo/DecoderError.h
Zaggy1024 da9ff31166 LibVideo: Make new DecoderError class to report useful errors
This allows runtime strings, so we can format the errors to make them
more helpful. Errors in the VP9 decoder will now print out a function,
filename and line number for where a read or bitstream requirement
has failed.

The DecoderErrorCategory enum will classify the errors so library users
can show general user-friendly error messages, while providing the
debug information separately.

Any non-DecoderErrorOr<> results can be wrapped by DECODER_TRY to
return from decoder functions. This will also add the extra information
mentioned above to the error message.
2022-10-09 20:32:40 -06:00

82 lines
2.7 KiB
C++

/*
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/Format.h>
#include <AK/SourceLocation.h>
#include <AK/String.h>
#include <errno.h>
namespace Video {
struct DecoderError;
template<typename T>
using DecoderErrorOr = ErrorOr<T, DecoderError>;
enum class DecoderErrorCategory : u32 {
Unknown,
IO,
// The input is corrupted.
Corrupted,
// The input uses features that are not yet implemented.
NotImplemented,
};
struct DecoderError {
public:
static DecoderError with_description(DecoderErrorCategory category, StringView description)
{
return DecoderError(category, description);
}
template<typename... Parameters>
static DecoderError format(DecoderErrorCategory category, CheckedFormatString<Parameters...>&& format_string, Parameters const&... parameters)
{
AK::VariadicFormatParams variadic_format_params { parameters... };
return DecoderError::with_description(category, String::vformatted(format_string.view(), variadic_format_params));
}
static DecoderError corrupted(StringView description, SourceLocation location = SourceLocation::current())
{
return DecoderError::format(DecoderErrorCategory::Corrupted, "{}: {}", location, description);
}
static DecoderError not_implemented(SourceLocation location = SourceLocation::current())
{
return DecoderError::format(DecoderErrorCategory::NotImplemented, "{} is not implemented", location.function_name());
}
DecoderErrorCategory category() { return m_category; }
StringView description() { return m_description; }
StringView string_literal() { return m_description; }
private:
DecoderError(DecoderErrorCategory category, String description)
: m_category(category)
, m_description(move(description))
{
}
DecoderErrorCategory m_category { DecoderErrorCategory::Unknown };
String m_description;
};
#define DECODER_TRY(category, expression) \
({ \
auto _result = ((expression)); \
if (_result.is_error()) [[unlikely]] { \
auto _error_string = _result.release_error().string_literal(); \
return DecoderError::format( \
((category)), "{}: {}", \
SourceLocation::current(), _error_string); \
} \
_result.release_value(); \
})
}