2021-11-06 01:18:43 +01:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2021 , Andreas Kling < andreas @ ladybird . org >
2021-11-06 01:18:43 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
2025-04-04 09:08:13 +02:00
# include <AK/Assertions.h>
2021-11-06 01:18:43 +01:00
# include <AK/StringView.h>
2021-12-14 23:02:23 +01:00
# include <AK/Variant.h>
2024-06-17 23:12:53 +01:00
# include <errno.h>
2021-11-06 01:18:43 +01:00
namespace AK {
2023-07-12 10:28:55 -04:00
class [ [ nodiscard ] ] Error {
2021-11-06 01:18:43 +01:00
public :
2023-02-09 13:47:28 -05:00
ALWAYS_INLINE Error ( Error & & ) = default ;
ALWAYS_INLINE Error & operator = ( Error & & ) = default ;
2025-04-04 09:08:13 +02:00
enum class Kind : u8 {
Errno ,
Syscall ,
Windows ,
StringLiteral
} ;
2023-07-12 10:28:55 -04:00
static Error from_errno ( int code )
2023-03-17 16:10:56 +00:00
{
VERIFY ( code ! = 0 ) ;
return Error ( code ) ;
}
2023-02-05 12:27:38 +02:00
2023-08-30 17:19:29 +10:00
# ifdef AK_OS_WINDOWS
2025-04-04 09:08:13 +02:00
static Error from_windows_error ( u32 windows_error ) ;
2024-12-08 22:00:56 +05:00
static Error from_windows_error ( ) ;
2023-08-30 17:19:29 +10:00
# endif
2025-05-10 16:24:35 -04:00
static Error from_syscall ( StringView syscall_name , int code )
2023-02-04 14:18:36 +02:00
{
2025-05-10 16:24:35 -04:00
return Error ( syscall_name , code ) ;
2023-02-04 14:18:36 +02:00
}
2023-07-12 10:28:55 -04:00
static Error from_string_view ( StringView string_literal ) { return Error ( string_literal ) ; }
2023-04-27 21:21:19 +03:30
2025-04-01 16:49:30 +02:00
template < OneOf < ByteString , String , FlyString > T >
2023-04-27 21:21:19 +03:30
static Error from_string_view ( T )
{
2023-12-16 17:49:34 +03:30
// `Error::from_string_view(ByteString::formatted(...))` is a somewhat common mistake, which leads to a UAF situation.
2023-04-27 21:21:19 +03:30
// If your string outlives this error and _isn't_ a temporary being passed to this function, explicitly call .view() on it to resolve to the StringView overload.
static_assert ( DependentFalse < T > , " Error::from_string_view(String) is almost always a use-after-free " ) ;
VERIFY_NOT_REACHED ( ) ;
}
2023-07-12 10:28:55 -04:00
static Error copy ( Error const & error )
2023-02-09 14:15:58 -05:00
{
return Error ( error ) ;
}
2022-07-11 17:57:32 +00:00
// NOTE: Prefer `from_string_literal` when directly typing out an error message:
//
// return Error::from_string_literal("Class: Some failure");
//
// If you need to return a static string based on a dynamic condition (like
// picking an error from an array), then prefer `from_string_view` instead.
template < size_t N >
2023-07-12 10:28:55 -04:00
ALWAYS_INLINE static Error from_string_literal ( char const ( & string_literal ) [ N ] )
2022-07-11 17:57:32 +00:00
{
return from_string_view ( StringView { string_literal , N - 1 } ) ;
}
2021-11-06 01:18:43 +01:00
2022-06-08 15:56:21 +02:00
bool operator = = ( Error const & other ) const
{
2025-04-04 09:08:13 +02:00
return m_code = = other . m_code & & m_string_literal = = other . m_string_literal & & m_kind = = other . m_kind ;
2022-06-08 15:56:21 +02:00
}
2021-11-06 01:18:43 +01:00
int code ( ) const { return m_code ; }
2023-02-04 14:18:36 +02:00
bool is_errno ( ) const
{
2025-05-10 15:17:58 +02:00
return m_kind = = Kind : : Errno | | m_kind = = Kind : : Syscall ;
2023-02-04 14:18:36 +02:00
}
2023-02-10 11:58:54 +01:00
bool is_syscall ( ) const
{
2025-04-04 09:08:13 +02:00
return m_kind = = Kind : : Syscall ;
}
bool is_windows_error ( ) const
{
return m_kind = = Kind : : Windows ;
}
bool is_string_literal ( ) const
{
return m_kind = = Kind : : StringLiteral ;
2023-02-10 11:58:54 +01:00
}
2023-02-04 14:18:36 +02:00
StringView string_literal ( ) const
{
return m_string_literal ;
}
2025-04-04 09:08:13 +02:00
Kind kind ( ) const
{
return m_kind ;
}
2021-11-06 01:18:43 +01:00
2021-11-07 01:30:35 +01:00
protected :
2025-04-04 09:08:13 +02:00
Error ( int code , Kind kind = Kind : : Errno )
2021-11-06 01:18:43 +01:00
: m_code ( code )
2025-04-04 09:08:13 +02:00
, m_kind ( kind )
2021-11-06 01:18:43 +01:00
{
}
2021-11-07 01:30:35 +01:00
private :
2021-11-06 01:18:43 +01:00
Error ( StringView string_literal )
: m_string_literal ( string_literal )
2025-04-04 09:08:13 +02:00
, m_kind ( Kind : : StringLiteral )
2021-11-06 01:18:43 +01:00
{
}
2025-05-10 16:24:35 -04:00
Error ( StringView syscall_name , int code )
2022-12-22 08:56:32 -05:00
: m_string_literal ( syscall_name )
2025-05-10 16:24:35 -04:00
, m_code ( code )
2025-04-04 09:08:13 +02:00
, m_kind ( Kind : : Syscall )
2021-11-22 16:00:53 +01:00
{
}
2023-02-09 13:47:28 -05:00
Error ( Error const & ) = default ;
Error & operator = ( Error const & ) = default ;
2021-11-06 01:18:43 +01:00
StringView m_string_literal ;
2023-02-04 14:18:36 +02:00
2022-12-22 08:56:32 -05:00
int m_code { 0 } ;
2023-02-04 14:18:36 +02:00
2025-04-04 09:08:13 +02:00
Kind m_kind { } ;
2021-11-06 01:18:43 +01:00
} ;
2022-12-10 15:29:20 +03:30
template < typename T , typename E >
2022-10-07 08:52:47 -04:00
class [ [ nodiscard ] ] ErrorOr {
2022-12-28 20:12:03 +00:00
template < typename U , typename F >
friend class ErrorOr ;
2021-11-06 01:18:43 +01:00
public :
2022-12-10 15:29:20 +03:30
using ResultType = T ;
using ErrorType = E ;
2022-10-17 00:06:11 +02:00
ErrorOr ( )
requires ( IsSame < T , Empty > )
2022-10-07 08:52:47 -04:00
: m_value_or_error ( Empty { } )
{
}
2021-11-06 01:18:43 +01:00
2022-12-09 20:08:09 +03:30
ALWAYS_INLINE ErrorOr ( ErrorOr & & ) = default ;
ALWAYS_INLINE ErrorOr & operator = ( ErrorOr & & ) = default ;
2023-02-09 13:47:28 -05:00
ErrorOr ( ErrorOr const & ) = delete ;
ErrorOr & operator = ( ErrorOr const & ) = delete ;
2022-12-09 20:08:09 +03:30
template < typename U >
ALWAYS_INLINE ErrorOr ( ErrorOr < U , ErrorType > & & value )
2022-12-28 20:12:03 +00:00
requires ( IsConvertible < U , T > )
: m_value_or_error ( value . m_value_or_error . visit ( [ ] ( U & v ) { return Variant < T , ErrorType > ( move ( v ) ) ; } , [ ] ( ErrorType & error ) { return Variant < T , ErrorType > ( move ( error ) ) ; } ) )
2022-12-09 20:08:09 +03:30
{
}
2021-11-08 00:36:35 +01:00
template < typename U >
2022-10-17 00:06:11 +02:00
ALWAYS_INLINE ErrorOr ( U & & value )
2022-12-09 20:08:09 +03:30
requires (
requires { T ( declval < U > ( ) ) ; } | | requires { ErrorType ( declval < RemoveCVReference < U > > ( ) ) ; } )
2022-10-07 08:52:47 -04:00
: m_value_or_error ( forward < U > ( value ) )
2021-11-08 00:36:35 +01:00
{
}
2021-12-14 23:02:23 +01:00
T & value ( )
2021-11-06 01:18:43 +01:00
{
2022-10-07 08:52:47 -04:00
return m_value_or_error . template get < T > ( ) ;
2021-11-06 01:18:43 +01:00
}
2022-10-07 08:52:47 -04:00
T const & value ( ) const { return m_value_or_error . template get < T > ( ) ; }
2021-11-06 01:18:43 +01:00
2022-10-07 08:52:47 -04:00
ErrorType & error ( ) { return m_value_or_error . template get < ErrorType > ( ) ; }
ErrorType const & error ( ) const { return m_value_or_error . template get < ErrorType > ( ) ; }
bool is_error ( ) const { return m_value_or_error . template has < ErrorType > ( ) ; }
2021-11-06 01:18:43 +01:00
2021-12-14 23:02:23 +01:00
T release_value ( ) { return move ( value ( ) ) ; }
ErrorType release_error ( ) { return move ( error ( ) ) ; }
2021-11-06 01:18:43 +01:00
2022-02-06 12:49:51 +00:00
T release_value_but_fixme_should_propagate_errors ( )
{
VERIFY ( ! is_error ( ) ) ;
return release_value ( ) ;
}
2021-11-06 11:29:32 +01:00
2021-11-06 01:18:43 +01:00
private :
2022-10-07 08:52:47 -04:00
Variant < T , ErrorType > m_value_or_error ;
2021-11-06 01:18:43 +01:00
} ;
2021-11-07 01:30:35 +01:00
template < typename ErrorType >
2022-10-07 08:52:47 -04:00
class [ [ nodiscard ] ] ErrorOr < void , ErrorType > : public ErrorOr < Empty , ErrorType > {
2021-11-06 01:18:43 +01:00
public :
2022-12-10 15:29:20 +03:30
using ResultType = void ;
2022-10-07 08:52:47 -04:00
using ErrorOr < Empty , ErrorType > : : ErrorOr ;
2021-11-06 01:18:43 +01:00
} ;
}
2022-11-26 12:18:30 +01:00
# if USING_AK_GLOBALLY
2021-11-06 10:34:14 +01:00
using AK : : Error ;
2021-11-06 01:18:43 +01:00
using AK : : ErrorOr ;
2022-11-26 12:18:30 +01:00
# endif