#pragma once #include #include #include "json.h" #include "route_config.h" static const char *route_config_json_keys[route_config_member_len] = {"route", "path", "admissions-percentile", "relative-deadline-us", "path_preprocess", "model-bias", "model-scale", "model-num-of-param", "model-beta1", "model-beta2", "http-resp-content-type"}; static inline int route_config_set_key_once(bool *did_set, enum route_config_member member) { if (did_set[member]) { debuglog("Redundant key %s\n", route_config_json_keys[member]); return -1; } did_set[member] = true; return 0; } static inline int route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t *tokens, size_t tokens_base, int tokens_size) { int i = tokens_base; char key[32] = {0}; bool did_set[route_config_member_len] = {false}; if (!has_valid_type(tokens[i], "Anonymous Route Config Object", JSMN_OBJECT, json_buf)) return -1; if (!is_nonempty_object(tokens[i], "Anonymous Route Config Object")) return -1; int route_key_count = tokens[i].size; for (int route_key_idx = 0; route_key_idx < route_key_count; route_key_idx++) { /* Advance to key */ i++; if (!is_valid_key(tokens[i])) return -1; if (!has_valid_size(tokens[i], key, 1)) return -1; /* Copy Key */ sprintf(key, "%.*s", tokens[i].end - tokens[i].start, json_buf + tokens[i].start); /* Advance to Value */ i++; if (strcmp(key, route_config_json_keys[route_config_member_route]) == 0) { if (!is_nonempty_string(tokens[i], key)) return -1; if (route_config_set_key_once(did_set, route_config_member_route) == -1) return -1; config->route = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start); } else if (strcmp(key, route_config_json_keys[route_config_member_path]) == 0) { if (!is_nonempty_string(tokens[i], key)) return -1; if (route_config_set_key_once(did_set, route_config_member_path) == -1) return -1; config->path = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start); } else if (strcmp(key, route_config_json_keys[route_config_member_path_preprocess]) == 0) { if (!is_nonempty_string(tokens[i], key)) return -1; if (route_config_set_key_once(did_set, route_config_member_path_preprocess) == -1) return -1; config->path_preprocess = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start); } else if (strcmp(key, route_config_json_keys[route_config_member_admissions_percentile]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_admissions_percentile) == -1) return -1; int rc = parse_uint8_t(tokens[i], json_buf, route_config_json_keys[route_config_member_admissions_percentile], &config->admissions_percentile); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_relative_deadline_us]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_relative_deadline_us) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_relative_deadline_us], &config->relative_deadline_us); if (rc < 0) return -1; } else if (strcmp(key, "expected-execution-us") == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; printf("The \"expected-execution-us\" field has been deprecated, so no need.\n"); } else if (strcmp(key, route_config_json_keys[route_config_member_model_bias]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_model_bias) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_model_bias], &config->model_bias); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_model_scale]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_model_scale) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_model_scale], &config->model_scale); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_model_num_of_param]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_model_num_of_param) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_model_num_of_param], &config->model_num_of_param); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_model_beta1]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_model_beta1) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_model_beta1], &config->model_beta1); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_model_beta2]) == 0) { if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1; if (route_config_set_key_once(did_set, route_config_member_model_beta2) == -1) return -1; int rc = parse_uint32_t(tokens[i], json_buf, route_config_json_keys[route_config_member_model_beta2], &config->model_beta2); if (rc < 0) return -1; } else if (strcmp(key, route_config_json_keys[route_config_member_http_resp_content_type]) == 0) { if (!is_nonempty_string(tokens[i], key)) return -1; if (route_config_set_key_once(did_set, route_config_member_http_resp_content_type) == -1) return -1; config->http_resp_content_type = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start); } else { fprintf(stderr, "%s is not a valid key\n", key); return -1; } } if (route_config_validate(config, did_set) < 0) return -1; return i; }