///|
/// Live-scan entry point for provider CLI coverage.
///
/// These two commands construct a native transport kind (`@native.NpcapKind` /
/// `@native.RawSocketKind`) and run a no-live / live provider scan. They live in
/// the isoproject top-level orchestration layer rather than
/// `fieldbus_core/cmd/main` because linking `driver/native` (required for the
/// extenum kind variants and their handler registrations to be live) is a
/// runtime concern that must not bleed into the fieldbus_core protocol layer —
/// the fieldbus-protocol boundary forbids fieldbus_core packages from importing
/// the lockwire native runtime. On wasm-gc the open raises before any I/O, so
/// the report records the no-live failure without touching a NIC.
fn main {
let args = @env.args()
if args.length() >= 2 && args[1] == "workbench-server-plan" {
let host = parse_text_option(args, "--host", default="127.0.0.1")
let port = parse_int_option(args, "--port", 8765)
let adapter = parse_text_option(args, "--adapter", default="windows-npcap")
let iface = parse_text_option(
args,
"--iface",
default=parse_text_option(args, "--interface", default=""),
)
let confirm = parse_text_option(
args,
"--confirm-interface",
default=parse_text_option(args, "--confirm", default=""),
)
let artifact_dir = parse_text_option(
args,
"--artifact-dir",
default="_build/isoproject-workbench",
)
let plan = @workbench.workbench_server_plan(
config=@workbench.workbench_server_config(
host~,
port~,
adapter~,
interface_name=iface,
confirm_interface_name=confirm,
allow_live=has_flag(args, "--allow-live"),
artifact_dir~,
),
)
for line in @workbench.workbench_server_plan_lines(plan) {
println(line)
}
return
}
if args.length() >= 2 && args[1] == "profinet-live-scan" {
let iface = parse_text_option(args, "--iface", default="")
let backend_label = parse_text_option(args, "--backend", default="npcap")
let allow_live = has_flag(args, "--allow-live")
let timeout = parse_int_option(args, "--timeout-ms", 3000)
let xid = parse_int_option(args, "--xid", 16909060)
let kind = if backend_label == "raw-socket" {
@native.RawSocketKind
} else {
@native.NpcapKind
}
let report = @live.live_scan_dcp_report(
kind,
iface,
allow_live,
timeout_ms=timeout,
xid~,
)
for line in @live.profinet_live_scan_report_lines(report) {
println(line)
}
return
}
if args.length() >= 2 && args[1] == "moonecat-live-scan" {
let iface = parse_text_option(args, "--iface", default="")
let backend_label = parse_text_option(args, "--backend", default="npcap")
let allow_live = has_flag(args, "--allow-live")
let timeout_ms = parse_int_option(args, "--timeout-ms", 1000)
let kind = if backend_label == "raw-socket" {
@native.RawSocketKind
} else {
@native.NpcapKind
}
let report = @mcat.moonecat_live_scan_report(
kind,
iface,
allow_live,
timeout_ns=timeout_ms.to_int64() * 1_000_000L,
)
for line in @mcat.moonecat_live_scan_report_lines(report) {
println(line)
}
return
}
print_help()
}
///|
fn print_help() -> Unit {
println("mokomoking2501/isoproject provider live-scan entry")
println("commands:")
println(
" - workbench-server-plan [--host 127.0.0.1] [--port 8765] [--adapter windows-npcap] [--iface NAME] [--confirm-interface NAME] [--artifact-dir DIR] [--allow-live]",
)
println(
" - profinet-live-scan --iface [--backend npcap|raw-socket] [--timeout-ms ] [--xid ] [--allow-live]",
)
println(
" - moonecat-live-scan --iface [--backend npcap|raw-socket] [--timeout-ms ] [--allow-live]",
)
println(
"default: no-live reports only; does not open NIC unless a route is later invoked with explicit live permission",
)
}
///|
fn parse_int_option(args : Array[String], name : String, default : Int) -> Int {
for i in 0.. Int {
if text == "" {
return 0
}
let bytes = @utf8.encode(text)
let mut value = 0
for ch in bytes {
if ch < b'0' || ch > b'9' {
return 0
}
value = value * 10 + ch.to_int() - b'0'.to_int()
}
value
}
///|
fn parse_text_option(
args : Array[String],
name : String,
default~ : String,
) -> String {
for i in 0.. Bool {
args.any(fn(arg) { arg == name })
}