///|
struct RpcOptions {
response : Bool
batch : Bool
no_response : Bool
request : String?
context : @rpc.ResponseContext?
legacy_errors : @rpc.LegacyErrorMode
}
///|
fn run_rpc_validation(
opts : ValueOptions,
version : @rpc.ProtocolVersion,
rpc_opts : RpcOptions,
assembled : @smithy.LoadResult,
) -> Int32 {
if !validation_model_ok(opts, assembled) {
return 1
}
let prepared = @rpc.PreparedService::prepare(
assembled.model.unwrap(),
opts.target,
version,
config=opts.config,
) catch {
@rpc.InvalidContract(id, message) =>
return value_problem(
opts,
"InvalidContract",
id.to_string() + ": " + message,
2,
source=Some("--service"),
)
@validation.UnsupportedConstraint(id, message) =>
return value_problem(
opts,
"UnsupportedConstraint",
id.to_string() + ": " + message,
2,
)
error =>
return value_problem(opts, "InvalidConfiguration", error.to_string(), 2)
}
let text = try {
if rpc_opts.no_response {
""
} else if opts.file == "-" {
read_stdin()
} else {
@fs.read_file_to_string(opts.file)
}
} catch {
_ =>
return value_problem(
opts, "InputRead", "I could not read the JSON-RPC message input.", 1,
)
}
let context = if rpc_opts.request is Some(file) {
let request = try {
if file == "-" {
read_stdin()
} else {
@fs.read_file_to_string(file)
}
} catch {
_ =>
return value_problem(
opts,
"InputRead",
"I could not read the original JSON-RPC request input.",
1,
source=Some(file),
)
}
Some(@rpc.OriginalRequest(request))
} else {
rpc_opts.context
}
if rpc_opts.batch {
if rpc_opts.response {
let batch_context = context.map(c => {
match c {
@rpc.EnvelopeOnly => @rpc.BatchEnvelopeOnly
@rpc.Method(name) => @rpc.BatchMethod(name)
@rpc.Operation(id) => @rpc.BatchOperation(id)
@rpc.OriginalRequest(text) => @rpc.OriginalBatch(text)
}
})
let result = prepared.validate_response_batch(
if rpc_opts.no_response {
None
} else {
Some(text)
},
context=batch_context,
)
if opts.diagnostics == JsonFindings {
println(@json.to_json(result).stringify())
} else {
print_rpc_findings(opts.file, result.findings)
}
return if result.is_valid() { 0 } else { 1 }
}
let result = prepared.validate_request_batch(text)
if opts.diagnostics == JsonFindings {
println(@json.to_json(result).stringify())
} else {
print_rpc_findings(opts.file, result.findings)
}
return if result.is_valid() { 0 } else { 1 }
}
if rpc_opts.response {
let result = prepared.validate_response(
text,
context~,
legacy_errors=rpc_opts.legacy_errors,
)
if opts.diagnostics == JsonFindings {
println(@json.to_json(result).stringify())
} else {
print_rpc_findings(opts.file, result.findings)
}
return if result.is_valid() { 0 } else { 1 }
}
let result = prepared.validate_request(text)
if opts.diagnostics == JsonFindings {
println(@json.to_json(result).stringify())
} else {
print_rpc_findings(opts.file, result.findings)
}
if result.is_valid() {
0
} else {
1
}
}
///|
fn print_rpc_findings(file : String, findings : Array[@rpc.Finding]) -> Unit {
for finding in findings {
let severity = if finding.severity == @validation.Error {
"error"
} else {
"advisory"
}
let offset = finding.offset.map(at => ":" + at.to_string()).unwrap_or("")
eprintln(
"\{file}\{offset}\{finding.path.pointer()}: \{severity}[\{finding.code.to_string()}] \{finding.shape}: \{finding.message}",
)
}
}