///|
/// Pure command dispatcher used by the `sdp-tool` executable and tests.
fn cli_failure(kind : String, message : String) -> String {
"{\"ok\":false,\"error\":{\"kind\":\"\{json_escape(kind)}\",\"message\":\"\{json_escape(message)}\"}}"
}
///|
fn cli_parse_failure(error : SdpError) -> String {
"{\"ok\":false,\"error\":{\"stage\":\"\{json_escape(error.stage())}\",\"kind\":\"\{json_escape(error.kind())}\",\"line\":\{error.line()},\"column\":\{error.column()},\"context\":\"\{json_escape(error.context())}\",\"message\":\"\{json_escape(error.message())}\"}}"
}
///|
fn codecs_json(document : SessionDescription) -> String {
let sb = StringBuilder()
sb.write_char('[')
for index, name in codec_names(document) {
if index > 0 {
sb.write_char(',')
}
sb.write_string("\"\{json_escape(name)}\"")
}
sb.write_char(']')
sb.to_string()
}
///|
fn cli_help() -> String {
"{\"ok\":true,\"commands\":[\"parse\",\"validate\",\"canonicalize\",\"inspect\",\"stats\",\"audit\",\"offer-answer\",\"version\",\"help\"],\"usage\":\"sdp-tool [answer-sdp]\"}"
}
///|
fn cli_parse(input : String) -> String {
match parse(input) {
Err(error) => cli_parse_failure(error)
Ok(document) => {
let stats = statistics(document)
"{\"ok\":true,\"version\":\{document.version()},\"session_name\":\"\{json_escape(document.session_name())}\",\"media\":\{stats.media_count()},\"attributes\":\{stats.session_attribute_count() + stats.media_attribute_count()}}"
}
}
}
///|
fn cli_validate(input : String) -> String {
match parse(input) {
Err(error) => cli_parse_failure(error)
Ok(document) => {
let report = validate(document)
"{\"ok\":true,\"valid\":\{report.is_valid()},\"errors\":\{report.error_count()},\"warnings\":\{report.warning_count()},\"info\":\{report.info_count()}}"
}
}
}
///|
fn cli_canonicalize(input : String) -> String {
match canonicalize(input) {
Err(error) => cli_parse_failure(error)
Ok(output) => "{\"ok\":true,\"sdp\":\"\{json_escape(output)}\"}"
}
}
///|
fn cli_inspect(input : String) -> String {
match parse(input) {
Err(error) => cli_parse_failure(error)
Ok(document) => {
let stats = statistics(document)
"{\"ok\":true,\"session\":\"\{json_escape(document.session_name())}\",\"media\":\{stats.media_count()},\"active\":\{stats.active_media_count()},\"rejected\":\{stats.rejected_media_count()},\"codecs\":\{codecs_json(document)}}"
}
}
}
///|
fn cli_stats(input : String) -> String {
match parse(input) {
Err(error) => cli_parse_failure(error)
Ok(document) =>
"{\"ok\":true,\"summary\":\"\{json_escape(statistics(document).to_text())}\"}"
}
}
///|
fn cli_audit(input : String) -> String {
match parse(input) {
Err(error) => cli_parse_failure(error)
Ok(document) => {
let report = audit(document)
"{\"ok\":true,\"high\":\{report.high_count()},\"medium\":\{report.medium_count()},\"low\":\{report.low_count()},\"findings\":\{report.finding_count()}}"
}
}
}
///|
fn cli_offer_answer(offer_input : String, answer_input : String) -> String {
let offer = match parse(offer_input) {
Err(error) => return cli_parse_failure(error)
Ok(value) => value
}
let answer = match parse(answer_input) {
Err(error) => return cli_parse_failure(error)
Ok(value) => value
}
let report = analyze_offer_answer(offer, answer)
"{\"ok\":true,\"compatible\":\{report.compatible()},\"issues\":\{report.issue_count()},\"accepted\":\{report.accepted_media()},\"rejected\":\{report.rejected_media()}}"
}
///|
/// Runs a CLI command. All outputs are one-line JSON and no branch raises.
pub fn run_cli(args : Array[String]) -> String {
if args.length() == 0 {
return cli_help()
}
let command = args[0].to_lower()
if command == "help" {
return cli_help()
}
if command == "version" {
return "{\"ok\":true,\"name\":\"moon-sdp\",\"version\":\"\{library_version()}\",\"iana_snapshot\":\"\{registry_snapshot_date()}\"}"
}
if command == "offer-answer" {
if args.length() != 3 {
return cli_failure(
"usage", "offer-answer requires offer and answer SDP arguments",
)
}
return cli_offer_answer(args[1], args[2])
}
if args.length() != 2 {
return cli_failure("usage", "command requires one SDP argument")
}
match command {
"parse" => cli_parse(args[1])
"validate" => cli_validate(args[1])
"canonicalize" => cli_canonicalize(args[1])
"inspect" => cli_inspect(args[1])
"stats" => cli_stats(args[1])
"audit" => cli_audit(args[1])
_ => cli_failure("unknown-command", "unknown command; use help")
}
}