Skip to content

Commit

Permalink
Switch to more efficient functions for json parsing (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyMusatkin authored Aug 2, 2024
1 parent ac3ac9d commit 04e777c
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 43 deletions.
4 changes: 2 additions & 2 deletions include/aws/sdkutils/endpoints_rule_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct aws_hash_table;
enum aws_endpoints_parameter_type {
AWS_ENDPOINTS_PARAMETER_STRING,
AWS_ENDPOINTS_PARAMETER_BOOLEAN,
AWS_ENDPOINTS_PARAMETER_STRING_ARRAY
AWS_ENDPOINTS_PARAMETER_STRING_ARRAY,
};
enum aws_endpoints_resolved_endpoint_type { AWS_ENDPOINTS_RESOLVED_ENDPOINT, AWS_ENDPOINTS_RESOLVED_ERROR };

Expand Down Expand Up @@ -244,7 +244,7 @@ AWS_SDKUTILS_API int aws_endpoints_request_context_add_string_array(
struct aws_allocator *allocator,
struct aws_endpoints_request_context *context,
struct aws_byte_cursor name,
struct aws_byte_cursor *values,
struct aws_byte_cursor *value_array,
size_t len);

/*
Expand Down
2 changes: 1 addition & 1 deletion include/aws/sdkutils/private/endpoints_types_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ enum aws_endpoints_fn_type {

enum aws_endpoints_value_type {
/* Special value to represent that any value type is expected from resolving an expresion.
Note a valid value for a value type. */
Not a valid value for a value type. */
AWS_ENDPOINTS_VALUE_ANY,

AWS_ENDPOINTS_VALUE_NONE,
Expand Down
1 change: 0 additions & 1 deletion source/endpoints_rule_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ static int s_init_top_level_scope(
val->value = value->default_value;
val->value.is_ref = true;
break;
break;
default:
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Unexpected parameter type.");
goto on_error;
Expand Down
63 changes: 25 additions & 38 deletions source/endpoints_ruleset.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static int s_try_parse_reference(const struct aws_json_value *node, struct aws_b

AWS_ZERO_STRUCT(*out_reference);

struct aws_json_value *ref_node = aws_json_value_get_from_object(node, aws_byte_cursor_from_c_str("ref"));
struct aws_json_value *ref_node = aws_json_value_get_from_object_c_str(node, "ref");
if (ref_node != NULL && aws_json_value_get_string(ref_node, out_reference)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to parse ref.");
AWS_ZERO_STRUCT(*out_reference);
Expand Down Expand Up @@ -329,7 +329,7 @@ static int s_parse_function(

AWS_ZERO_STRUCT(*function);

struct aws_json_value *fn_node = aws_json_value_get_from_object(node, aws_byte_cursor_from_c_str("fn"));
struct aws_json_value *fn_node = aws_json_value_get_from_object_c_str(node, "fn");
if (fn_node == NULL) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Node is not a function.");
goto on_error;
Expand Down Expand Up @@ -358,7 +358,7 @@ static int s_parse_function(
goto on_error;
}

struct aws_json_value *argv_node = aws_json_value_get_from_object(node, aws_byte_cursor_from_c_str("argv"));
struct aws_json_value *argv_node = aws_json_value_get_from_object_c_str(node, "argv");
if (argv_node == NULL || !aws_json_value_is_array(argv_node)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "No argv or unexpected type.");
goto on_error;
Expand Down Expand Up @@ -395,7 +395,7 @@ static int s_on_parameter_key(

/* required fields */
struct aws_byte_cursor type_cur;
struct aws_json_value *type_node = aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("type"));
struct aws_json_value *type_node = aws_json_value_get_from_object_c_str(value, "type");
if (type_node == NULL || aws_json_value_get_string(type_node, &type_cur)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract parameter type.");
goto on_error;
Expand All @@ -415,8 +415,7 @@ static int s_on_parameter_key(

parameter->type = type;

struct aws_json_value *documentation_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("documentation"));
struct aws_json_value *documentation_node = aws_json_value_get_from_object_c_str(value, "documentation");

/* TODO: spec calls for documentation to be required, but several test-cases
are missing docs on parameters */
Expand All @@ -428,16 +427,15 @@ static int s_on_parameter_key(
}

/* optional fields */
struct aws_json_value *built_in_node = aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("builtIn"));
struct aws_json_value *built_in_node = aws_json_value_get_from_object_c_str(value, "builtIn");
if (built_in_node != NULL) {
if (aws_json_value_get_string(built_in_node, &parameter->built_in)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected type for built-in parameter field.");
goto on_error;
}
}

struct aws_json_value *required_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("required"));
struct aws_json_value *required_node = aws_json_value_get_from_object_c_str(value, "required");
if (required_node != NULL) {
if (!aws_json_value_is_boolean(required_node)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected type for required parameter field.");
Expand All @@ -446,7 +444,7 @@ static int s_on_parameter_key(
aws_json_value_get_boolean(required_node, &parameter->is_required);
}

struct aws_json_value *default_node = aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("default"));
struct aws_json_value *default_node = aws_json_value_get_from_object_c_str(value, "default");
parameter->has_default_value = default_node != NULL;
if (default_node != NULL) {
if (type == AWS_ENDPOINTS_PARAMETER_STRING && aws_json_value_is_string(default_node)) {
Expand Down Expand Up @@ -488,19 +486,17 @@ static int s_on_parameter_key(
}
}

struct aws_json_value *deprecated_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("deprecated"));
struct aws_json_value *deprecated_node = aws_json_value_get_from_object_c_str(value, "deprecated");
if (deprecated_node != NULL) {
struct aws_json_value *deprecated_message_node =
aws_json_value_get_from_object(deprecated_node, aws_byte_cursor_from_c_str("message"));
aws_json_value_get_from_object_c_str(deprecated_node, "message");
if (deprecated_message_node != NULL &&
aws_json_value_get_string(deprecated_message_node, &parameter->deprecated_message)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected value for deprecated message.");
goto on_error;
}

struct aws_json_value *deprecated_since_node =
aws_json_value_get_from_object(deprecated_node, aws_byte_cursor_from_c_str("since"));
struct aws_json_value *deprecated_since_node = aws_json_value_get_from_object_c_str(deprecated_node, "since");
if (deprecated_since_node != NULL &&
aws_json_value_get_string(deprecated_since_node, &parameter->deprecated_since)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected value for deprecated since.");
Expand Down Expand Up @@ -540,8 +536,7 @@ static int s_on_condition_element(
goto on_error;
}

struct aws_json_value *assign_node =
aws_json_value_get_from_object(condition_node, aws_byte_cursor_from_c_str("assign"));
struct aws_json_value *assign_node = aws_json_value_get_from_object_c_str(condition_node, "assign");
if (assign_node != NULL && aws_json_value_get_string(assign_node, &condition.assign)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected value for assign.");
goto on_error;
Expand Down Expand Up @@ -619,7 +614,7 @@ static int s_parse_endpoints_rule_data_endpoint(
AWS_PRECONDITION(data_rule);

data_rule->allocator = allocator;
struct aws_json_value *url_node = aws_json_value_get_from_object(rule_node, aws_byte_cursor_from_c_str("url"));
struct aws_json_value *url_node = aws_json_value_get_from_object_c_str(rule_node, "url");
if (url_node == NULL || aws_json_value_is_string(url_node)) {
data_rule->url.type = AWS_ENDPOINTS_EXPR_STRING;
aws_json_value_get_string(url_node, &data_rule->url.e.string);
Expand All @@ -642,8 +637,7 @@ static int s_parse_endpoints_rule_data_endpoint(
}
}

struct aws_json_value *properties_node =
aws_json_value_get_from_object(rule_node, aws_byte_cursor_from_c_str("properties"));
struct aws_json_value *properties_node = aws_json_value_get_from_object_c_str(rule_node, "properties");
if (properties_node != NULL) {
aws_byte_buf_init(&data_rule->properties, allocator, 0);

Expand All @@ -668,8 +662,7 @@ static int s_parse_endpoints_rule_data_endpoint(
aws_hash_callback_string_destroy,
s_callback_headers_destroy);

struct aws_json_value *headers_node =
aws_json_value_get_from_object(rule_node, aws_byte_cursor_from_c_str("headers"));
struct aws_json_value *headers_node = aws_json_value_get_from_object_c_str(rule_node, "headers");
if (headers_node != NULL) {

if (s_init_members_from_json(allocator, headers_node, &data_rule->headers, s_on_headers_key)) {
Expand Down Expand Up @@ -738,7 +731,7 @@ static int s_parse_endpoints_rule_data_tree(
AWS_PRECONDITION(rule_node);
AWS_PRECONDITION(rule_data);

struct aws_json_value *rules_node = aws_json_value_get_from_object(rule_node, aws_byte_cursor_from_c_str("rules"));
struct aws_json_value *rules_node = aws_json_value_get_from_object_c_str(rule_node, "rules");
if (rules_node == NULL || !aws_json_value_is_array(rules_node)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Rules node is missing or unexpected type.");
return aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_PARSE_FAILED);
Expand Down Expand Up @@ -769,7 +762,7 @@ static int s_on_rule_element(

/* Required fields */
struct aws_byte_cursor type_cur;
struct aws_json_value *type_node = aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("type"));
struct aws_json_value *type_node = aws_json_value_get_from_object_c_str(value, "type");
if (type_node == NULL || aws_json_value_get_string(type_node, &type_cur)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract rule type.");
return aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_PARSE_FAILED);
Expand All @@ -791,8 +784,7 @@ static int s_on_rule_element(
AWS_ZERO_STRUCT(rule);
rule.type = type;

struct aws_json_value *conditions_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("conditions"));
struct aws_json_value *conditions_node = aws_json_value_get_from_object_c_str(value, "conditions");
if (conditions_node == NULL || !aws_json_value_is_array(conditions_node)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Conditions node missing.");
goto on_error;
Expand All @@ -809,8 +801,7 @@ static int s_on_rule_element(

switch (type) {
case AWS_ENDPOINTS_RULE_ENDPOINT: {
struct aws_json_value *endpoint_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("endpoint"));
struct aws_json_value *endpoint_node = aws_json_value_get_from_object_c_str(value, "endpoint");
if (endpoint_node == NULL ||
s_parse_endpoints_rule_data_endpoint(wrapper->allocator, endpoint_node, &rule.rule_data.endpoint)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract endpoint rule data.");
Expand All @@ -819,8 +810,7 @@ static int s_on_rule_element(
break;
}
case AWS_ENDPOINTS_RULE_ERROR: {
struct aws_json_value *error_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("error"));
struct aws_json_value *error_node = aws_json_value_get_from_object_c_str(value, "error");
if (error_node == NULL ||
s_parse_endpoints_rule_data_error(wrapper->allocator, error_node, &rule.rule_data.error)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract error rule data.");
Expand All @@ -840,8 +830,7 @@ static int s_on_rule_element(
}

/* Optional fields */
struct aws_json_value *documentation_node =
aws_json_value_get_from_object(value, aws_byte_cursor_from_c_str("documentation"));
struct aws_json_value *documentation_node = aws_json_value_get_from_object_c_str(value, "documentation");
if (documentation_node != NULL) {
if (aws_json_value_get_string(documentation_node, &rule.documentation)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract parameter documentation.");
Expand Down Expand Up @@ -875,7 +864,7 @@ static int s_init_ruleset_from_json(

ruleset->json_root = root;

struct aws_json_value *version_node = aws_json_value_get_from_object(root, aws_byte_cursor_from_c_str("version"));
struct aws_json_value *version_node = aws_json_value_get_from_object_c_str(root, "version");
if (version_node == NULL || aws_json_value_get_string(version_node, &ruleset->version)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract version.");
aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_UNSUPPORTED_RULESET);
Expand All @@ -890,8 +879,7 @@ static int s_init_ruleset_from_json(
}
#endif

struct aws_json_value *service_id_node =
aws_json_value_get_from_object(root, aws_byte_cursor_from_c_str("serviceId"));
struct aws_json_value *service_id_node = aws_json_value_get_from_object_c_str(root, "serviceId");

if (service_id_node != NULL && aws_json_value_get_string(service_id_node, &ruleset->service_id)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract serviceId.");
Expand All @@ -908,16 +896,15 @@ static int s_init_ruleset_from_json(
NULL,
s_callback_endpoints_parameter_destroy);

struct aws_json_value *parameters_node =
aws_json_value_get_from_object(root, aws_byte_cursor_from_c_str("parameters"));
struct aws_json_value *parameters_node = aws_json_value_get_from_object_c_str(root, "parameters");
if (parameters_node == NULL ||
s_init_members_from_json(allocator, parameters_node, &ruleset->parameters, s_on_parameter_key)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Failed to extract parameters.");
aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_PARSE_FAILED);
goto on_error;
}

struct aws_json_value *rules_node = aws_json_value_get_from_object(root, aws_byte_cursor_from_c_str("rules"));
struct aws_json_value *rules_node = aws_json_value_get_from_object_c_str(root, "rules");
if (rules_node == NULL || !aws_json_value_is_array(rules_node)) {
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_PARSING, "Unexpected type for rules node.");
aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_PARSE_FAILED);
Expand Down
1 change: 0 additions & 1 deletion source/endpoints_types_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ int aws_endpoints_deep_copy_parameter_value(
AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Unexpected value type.");
return aws_raise_error(AWS_ERROR_INVALID_STATE);
}

return AWS_OP_SUCCESS;

on_error:
Expand Down

0 comments on commit 04e777c

Please sign in to comment.