in source/Model.cpp [902:1046]
Model Model::from_json(
const Method* method,
const Json::Value& value,
Context& context) {
JsonValidation::validate_object(value);
Modes modes;
for (auto mode_value :
JsonValidation::null_or_array(value, /* field */ "modes")) {
auto mode = string_to_model_mode(JsonValidation::string(mode_value));
if (!mode) {
throw JsonValidationError(value, /* field */ "modes", "valid mode");
}
modes.set(*mode, true);
}
Model model(method, context, modes);
for (auto generation_value :
JsonValidation::null_or_array(value, /* field */ "generations")) {
auto port = AccessPath(Root(Root::Kind::Return));
if (generation_value.isMember("port")) {
JsonValidation::string(generation_value, /* field */ "port");
port = AccessPath::from_json(generation_value["port"]);
} else if (generation_value.isMember("caller_port")) {
JsonValidation::string(generation_value, /* field */ "caller_port");
port = AccessPath::from_json(generation_value["caller_port"]);
}
model.add_generation(port, Frame::from_json(generation_value, context));
}
for (auto parameter_source_value :
JsonValidation::null_or_array(value, /* field */ "parameter_sources")) {
std::string port_field =
parameter_source_value.isMember("port") ? "port" : "caller_port";
JsonValidation::string(parameter_source_value, /* field */ port_field);
auto port = AccessPath::from_json(parameter_source_value[port_field]);
model.add_parameter_source(
port, Frame::from_json(parameter_source_value, context));
}
for (auto source_value :
JsonValidation::null_or_array(value, /* field */ "sources")) {
auto port = AccessPath(Root(Root::Kind::Return));
if (source_value.isMember("port")) {
JsonValidation::string(source_value, /* field */ "port");
port = AccessPath::from_json(source_value["port"]);
} else if (source_value.isMember("caller_port")) {
JsonValidation::string(source_value, /* field */ "caller_port");
port = AccessPath::from_json(source_value["caller_port"]);
}
auto source = Frame::from_json(source_value, context);
if (port.root().is_argument()) {
model.add_parameter_source(port, source);
} else {
model.add_generation(port, source);
}
}
for (auto sink_value :
JsonValidation::null_or_array(value, /* field */ "sinks")) {
std::string port_field =
sink_value.isMember("port") ? "port" : "caller_port";
JsonValidation::string(sink_value, /* field */ port_field);
auto port = AccessPath::from_json(sink_value[port_field]);
model.add_sink(port, Frame::from_json(sink_value, context));
}
for (auto propagation_value :
JsonValidation::null_or_array(value, /* field */ "propagation")) {
JsonValidation::string(propagation_value, /* field */ "output");
auto output = AccessPath::from_json(propagation_value["output"]);
model.add_propagation(
Propagation::from_json(propagation_value, context), output);
}
for (auto sanitizer_value :
JsonValidation::null_or_array(value, /* field */ "sanitizers")) {
auto sanitizer = Sanitizer::from_json(sanitizer_value, context);
if (!sanitizer_value.isMember("port")) {
model.add_global_sanitizer(sanitizer);
} else {
auto root = Root::from_json(sanitizer_value["port"]);
model.add_port_sanitizers(SanitizerSet(sanitizer), root);
}
}
for (auto attach_to_sources_value :
JsonValidation::null_or_array(value, /* field */ "attach_to_sources")) {
JsonValidation::string(attach_to_sources_value, /* field */ "port");
auto root = Root::from_json(attach_to_sources_value["port"]);
JsonValidation::null_or_array(
attach_to_sources_value, /* field */ "features");
auto features =
FeatureSet::from_json(attach_to_sources_value["features"], context);
model.add_attach_to_sources(root, features);
}
for (auto attach_to_sinks_value :
JsonValidation::null_or_array(value, /* field */ "attach_to_sinks")) {
JsonValidation::string(attach_to_sinks_value, /* field */ "port");
auto root = Root::from_json(attach_to_sinks_value["port"]);
JsonValidation::null_or_array(
attach_to_sinks_value, /* field */ "features");
auto features =
FeatureSet::from_json(attach_to_sinks_value["features"], context);
model.add_attach_to_sinks(root, features);
}
for (auto attach_to_propagations_value : JsonValidation::null_or_array(
value, /* field */ "attach_to_propagations")) {
JsonValidation::string(attach_to_propagations_value, /* field */ "port");
auto root = Root::from_json(attach_to_propagations_value["port"]);
JsonValidation::null_or_array(
attach_to_propagations_value, /* field */ "features");
auto features = FeatureSet::from_json(
attach_to_propagations_value["features"], context);
model.add_attach_to_propagations(root, features);
}
for (auto add_features_to_arguments_value : JsonValidation::null_or_array(
value, /* field */ "add_features_to_arguments")) {
JsonValidation::string(add_features_to_arguments_value, /* field */ "port");
auto root = Root::from_json(add_features_to_arguments_value["port"]);
JsonValidation::null_or_array(
add_features_to_arguments_value, /* field */ "features");
auto features = FeatureSet::from_json(
add_features_to_arguments_value["features"], context);
model.add_add_features_to_arguments(root, features);
}
if (value.isMember("inline_as")) {
JsonValidation::string(value, /* field */ "inline_as");
model.set_inline_as(
AccessPathConstantDomain(AccessPath::from_json(value["inline_as"])));
}
// We cannot parse issues for now.
if (value.isMember("issues")) {
throw JsonValidationError(
value, /* field */ std::nullopt, /* expected */ "model without issues");
}
return model;
}