2024-09-26 11:35:28 -04:00
/*
* Copyright ( c ) 2024 , Tim Flynn < trflynn89 @ ladybird . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
# include <AK/JsonArray.h>
# include <AK/JsonObject.h>
# include <AK/JsonValue.h>
2025-02-17 13:58:21 -05:00
# include <AK/String.h>
2024-09-26 16:46:15 -04:00
# include <LibJS/Runtime/Value.h>
2024-09-26 11:35:28 -04:00
# include <LibWeb/WebDriver/Error.h>
namespace Web : : WebDriver {
2025-02-17 13:58:21 -05:00
template < typename PropertyType = String >
2024-09-26 16:33:35 -04:00
static ErrorOr < PropertyType , WebDriver : : Error > get_property ( JsonObject const & payload , StringView key )
2024-09-26 11:35:28 -04:00
{
2024-09-26 16:33:35 -04:00
auto property = payload . get ( key ) ;
2024-09-26 11:35:28 -04:00
if ( ! property . has_value ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " No property called '{}' present " , key ) ) ) ;
2024-09-26 11:35:28 -04:00
2024-09-26 16:46:15 -04:00
auto is_safe_number = [ ] < typename T > ( T value ) {
if constexpr ( sizeof ( T ) > = 8 ) {
if ( value > static_cast < T > ( JS : : MAX_ARRAY_LIKE_INDEX ) )
return false ;
if constexpr ( IsSigned < T > ) {
if ( value < - static_cast < T > ( JS : : MAX_ARRAY_LIKE_INDEX ) )
return false ;
}
}
return true ;
} ;
2025-02-17 13:58:21 -05:00
if constexpr ( IsSame < PropertyType , String > ) {
2024-09-26 11:35:28 -04:00
if ( ! property - > is_string ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not a String " , key ) ) ) ;
return property - > as_string ( ) ;
2024-09-26 11:35:28 -04:00
} else if constexpr ( IsSame < PropertyType , bool > ) {
if ( ! property - > is_bool ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not a Boolean " , key ) ) ) ;
2024-09-26 11:35:28 -04:00
return property - > as_bool ( ) ;
2024-09-26 16:33:35 -04:00
} else if constexpr ( IsIntegral < PropertyType > ) {
2024-09-26 16:46:15 -04:00
if ( auto maybe_number = property - > get_integer < PropertyType > ( ) ; maybe_number . has_value ( ) & & is_safe_number ( * maybe_number ) )
2024-09-26 16:33:35 -04:00
return * maybe_number ;
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not an Integer " , key ) ) ) ;
2024-09-26 16:33:35 -04:00
} else if constexpr ( IsSame < PropertyType , double > ) {
2024-09-26 16:46:15 -04:00
if ( auto maybe_number = property - > get_double_with_precision_loss ( ) ; maybe_number . has_value ( ) & & is_safe_number ( * maybe_number ) )
2024-09-26 16:33:35 -04:00
return * maybe_number ;
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not a Number " , key ) ) ) ;
2024-09-26 11:35:28 -04:00
} else if constexpr ( IsSame < PropertyType , JsonArray const * > ) {
if ( ! property - > is_array ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not an Array " , key ) ) ) ;
2024-09-26 11:35:28 -04:00
return & property - > as_array ( ) ;
} else if constexpr ( IsSame < PropertyType , JsonObject const * > ) {
if ( ! property - > is_object ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' is not an Object " , key ) ) ) ;
2024-09-26 11:35:28 -04:00
return & property - > as_object ( ) ;
} else {
static_assert ( DependentFalse < PropertyType > , " get_property invoked with unknown property type " ) ;
VERIFY_NOT_REACHED ( ) ;
}
}
2025-02-17 13:58:21 -05:00
template < typename PropertyType = String >
2024-09-26 16:33:35 -04:00
static ErrorOr < PropertyType , WebDriver : : Error > get_property ( JsonValue const & payload , StringView key )
{
if ( ! payload . is_object ( ) )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( ErrorCode : : InvalidArgument , " Payload is not a JSON object " sv ) ;
2024-09-26 16:33:35 -04:00
return get_property < PropertyType > ( payload . as_object ( ) , key ) ;
}
2025-02-17 13:58:21 -05:00
template < typename PropertyType = String >
2024-09-26 16:33:35 -04:00
static ErrorOr < Optional < PropertyType > , WebDriver : : Error > get_optional_property ( JsonObject const & object , StringView key )
{
if ( ! object . has ( key ) )
return OptionalNone { } ;
return get_property < PropertyType > ( object , key ) ;
}
template < Arithmetic PropertyType >
static ErrorOr < PropertyType , WebDriver : : Error > get_property_with_limits ( JsonObject const & object , StringView key , Optional < PropertyType > min , Optional < PropertyType > max )
{
auto value = TRY ( get_property < PropertyType > ( object , key ) ) ;
if ( min . has_value ( ) & & value < * min )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( WebDriver : : ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' must not be less than {} " , key , * min ) ) ) ;
2024-09-26 16:33:35 -04:00
if ( max . has_value ( ) & & value > * max )
2025-02-17 13:58:21 -05:00
return WebDriver : : Error : : from_code ( WebDriver : : ErrorCode : : InvalidArgument , MUST ( String : : formatted ( " Property '{}' must not be greater than {} " , key , * max ) ) ) ;
2024-09-26 16:33:35 -04:00
return value ;
}
template < Arithmetic PropertyType >
static ErrorOr < Optional < PropertyType > , WebDriver : : Error > get_optional_property_with_limits ( JsonObject const & object , StringView key , Optional < PropertyType > min , Optional < PropertyType > max )
{
if ( ! object . has ( key ) )
return OptionalNone { } ;
return get_property_with_limits < PropertyType > ( object , key , min , max ) ;
}
2024-09-26 11:35:28 -04:00
}