// ===== jsonld 命令行薄壳(共享核心)=====
// 错误契约:文案一律 eprintln(stderr;stdout 保净供管道),退出码恒 0
// (工具链无 exit API——moonttl / skelgen cmd 同款先例)。
///|
async fn dispatch(invocation : CliInvocation) -> Unit {
match invocation.verb {
"expand" => run_expand(invocation)
"compact" => run_compact(invocation)
"flatten" => run_flatten(invocation)
"frame" => run_frame(invocation)
"to-rdf" => run_to_rdf(invocation)
"from-rdf" => run_from_rdf(invocation)
"canonicalize" => run_canonicalize(invocation)
"json-canonical" => run_json_canonical(invocation)
unknown => {
eprintln("jsonld:未知命令 \{unknown}")
print_usage(true)
}
}
}
///|
/// 选项构造:全字段显式(跨包构造规则);错误面 / 语义全在库侧。
/// 缺省与套件 harness 同款(compact_arrays=true / frame_expansion=false)。
fn make_options(base : String?, mode_1_0 : Bool) -> @jsonld.JsonLdOptions {
let processing_mode = if mode_1_0 {
@jsonld.ProcessingMode::JsonLd10
} else {
@jsonld.ProcessingMode::JsonLd11
}
{
base,
expand_context: None,
processing_mode,
load_context: None,
rdf_direction: None,
produce_generalized_rdf: false,
compact_arrays: true,
compact_to_relative: true,
frame_expansion: false,
omit_graph: false,
use_native_types: false,
use_rdf_type: false,
}
}
///|
async fn read_text(path : String) -> String? {
try {
let bytes = @fs.read_file(path).binary()
Some(@utf8.decode(bytes))
} catch {
_ => None
}
}
///|
/// 错误文案:变体名即错误类别(JsonLdError 无 Show,九臂直出)。
fn error_text(error : @jsonld.JsonLdError) -> String {
match error {
Syntax(text) => "syntax: \{text}"
InvalidContext(text) => "invalid context: \{text}"
InvalidIri(text) => "invalid IRI: \{text}"
InvalidValue(text) => "invalid value: \{text}"
InvalidList(text) => "invalid list: \{text}"
Unsupported(text) => "unsupported: \{text}"
ContextOverflow(text) => "context overflow: \{text}"
LoadingDocumentFailed(text) => "loading document failed: \{text}"
InvalidScriptElement(text) => "invalid script element: \{text}"
}
}
///|
/// 第 index 个位置输入:不足额或读不到文件时打错误(stderr)并返回 None。
async fn load_positional(
invocation : CliInvocation,
index : Int,
label : String,
) -> String? {
if index >= invocation.positionals.length() {
eprintln("jsonld \{invocation.verb}:缺少 <\{label}> 输入")
return None
}
let path = invocation.positionals[index]
match read_text(path) {
Some(text) => Some(text)
None => {
eprintln("jsonld \{invocation.verb}:无法读取 \{path}")
None
}
}
}
///|
/// JSON 结果打印:Ok 出 stdout,Err 出 stderr。
fn print_json(
label : String,
result : Result[@jsonld.JsonValue, @jsonld.JsonLdError],
) -> Unit {
match result {
Ok(value) => println(@jsonld.render_json(value))
Err(error) => eprintln("jsonld \{label} 失败:\{error_text(error)}")
}
}
///|
async fn first_positional(
invocation : CliInvocation,
label : String,
) -> String? {
load_positional(invocation, 0, label)
}