///|
fn main {
let args = @env.args()
if args.length() >= 2 && args[1] == "m5-digest" {
println(@wasm.p2p_digest_line(seed=parse_seed(args, default=42)))
return
}
if args.length() >= 2 && args[1] == "cl7-pcapng-hex" {
let seed = parse_seed(args, default=42)
let bytes = @wasm.p2p_trace_log(seed~, backend=@core.SimNative).to_pcapng(
seed~,
)
println(bytes_to_hex(bytes))
return
}
if args.length() >= 2 && args[1] == "m6-segment" {
println(
@sim.run_segment_toy(seed=parse_seed(args, default=42)).timeline_text(),
)
return
}
if args.length() >= 2 && args[1] == "k1-partition-heal" {
println(
@sim.run_fabric_partition_heal(seed=parse_seed(args, default=42)).timeline_text(),
)
return
}
if args.length() >= 2 && args[1] == "l3f-switched-fabric" {
println(
@sim.run_switched_fabric_offline(seed=parse_seed(args, default=704)).timeline_text(),
)
return
}
if args.length() >= 2 && args[1] == "l3g-switched-fabric-qos-irt" {
println(
@sim.run_switched_fabric_qos_irt_offline(
seed=parse_seed(args, default=734),
).timeline_text(),
)
return
}
if args.length() >= 2 && args[1] == "d57-link-readiness" {
println(
@lib.link_readiness_matrix_report(seed=parse_seed(args, default=757)).to_text(),
)
return
}
if args.length() >= 2 && args[1] == "npcap-live-smoke" {
let iface = parse_text_option(args, "--iface", default="")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let filter = parse_text_option(args, "--filter", default="")
let report = @lib.native_npcap_manual_live_smoke(
iface,
snaplen~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
filter_expression=filter,
)
println(npcap_live_smoke_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-list-ifaces" {
println(
npcap_interface_list_text(@lib.native_npcap_interface_list_report()),
)
return
}
if args.length() >= 2 && args[1] == "raw-socket-list-ifaces" {
println(
raw_socket_interface_list_text(
@lib.native_raw_socket_interface_list_report(),
),
)
return
}
if args.length() >= 2 && args[1] == "udp-loopback-smoke" {
let timeout = parse_positive_int_option(args, "--timeout-ms", default=100)
let result : Result[@lib.NativeUdpLoopbackSmokeReport, Error] = Result::Ok(
@lib.native_udp_loopback_smoke(timeout_ms=timeout),
) catch {
err => Result::Err(err)
}
match result {
Ok(report) => println(udp_loopback_smoke_line(report))
Err(_) => println(udp_loopback_smoke_failure_line(timeout))
}
return
}
if args.length() >= 2 && args[1] == "raw-socket-smoke" {
let iface = parse_text_option(args, "--iface", default="")
let allow_send = has_flag(args, "--allow-send")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let attempts = parse_positive_int_option(args, "--attempts", default=3)
let ethertype = parse_hex_u16_option(args, "--ethertype", default=0x88b5)
let frame = parse_ethernet_frame_template(args)
let report = @lib.native_raw_socket_manual_smoke(
iface,
allow_send~,
allow_capture~,
ethertype~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
capture_attempts=attempts,
frame~,
)
println(raw_socket_smoke_line(report))
return
}
if args.length() >= 2 && args[1] == "raw-socket-roundtrip-pcap" {
let iface = parse_text_option(args, "--iface", default="")
let out = parse_text_option(args, "--out", default="")
let allow_send = has_flag(args, "--allow-send")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let attempts = parse_positive_int_option(args, "--attempts", default=3)
let ethertype = parse_hex_u16_option(args, "--ethertype", default=0x88b5)
let frame = parse_ethernet_frame_template(args)
let report = @lib.native_raw_socket_roundtrip_pcap_artifact(
iface,
out,
allow_send~,
allow_capture~,
capture_attempts=attempts,
ethertype~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
frame~,
)
println(raw_socket_roundtrip_pcap_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-send-smoke" {
let iface = parse_text_option(args, "--iface", default="")
let allow_send = has_flag(args, "--allow-send")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let frame = parse_ethernet_frame_template(args)
let report = @lib.native_npcap_manual_send_smoke(
iface,
allow_send~,
snaplen~,
open_timeout_ms=timeout,
frame~,
)
println(npcap_send_smoke_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-roundtrip-smoke" {
let iface = parse_text_option(args, "--iface", default="")
let allow_send = has_flag(args, "--allow-send")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let attempts = parse_positive_int_option(args, "--attempts", default=3)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let filter = parse_text_option(args, "--filter", default="")
let frame = parse_ethernet_frame_template(args)
let report = @lib.native_npcap_send_capture_roundtrip(
iface,
allow_send~,
allow_capture~,
capture_attempts=attempts,
snaplen~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
filter_expression=filter,
frame~,
)
println(npcap_roundtrip_smoke_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-roundtrip-pcap" {
let iface = parse_text_option(args, "--iface", default="")
let out = parse_text_option(args, "--out", default="")
let allow_send = has_flag(args, "--allow-send")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let attempts = parse_positive_int_option(args, "--attempts", default=3)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let filter = parse_text_option(args, "--filter", default="")
let frame = parse_ethernet_frame_template(args)
let report = @lib.native_npcap_roundtrip_pcap_artifact(
iface,
out,
allow_send~,
allow_capture~,
capture_attempts=attempts,
snaplen~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
filter_expression=filter,
frame~,
)
println(npcap_roundtrip_pcap_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-capture-pcap" {
let iface = parse_text_option(args, "--iface", default="")
let out = parse_text_option(args, "--out", default="")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let filter = parse_text_option(args, "--filter", default="")
let report = @lib.native_npcap_capture_pcap_artifact(
iface,
out,
allow_capture~,
snaplen~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
filter_expression=filter,
)
println(npcap_capture_pcap_line(report))
return
}
if args.length() >= 2 && args[1] == "npcap-capture-frame-pool" {
let iface = parse_text_option(args, "--iface", default="")
let allow_capture = has_flag(args, "--allow-capture")
let timeout = parse_positive_int_option(args, "--timeout-ms", default=50)
let snaplen = parse_positive_int_option(args, "--snaplen", default=65_535)
let filter = parse_text_option(args, "--filter", default="")
let report = @lib.native_npcap_capture_frame_pool(
iface,
allow_capture~,
snaplen~,
open_timeout_ms=timeout,
capture_timeout_ms=timeout,
filter_expression=filter,
)
println(npcap_capture_frame_pool_line(report))
return
}
println("\{@lib.framework_name} / \{@lib.project_name}")
println(@lib.m0_scope())
println("packages:")
for id in @lib.package_ids() {
println(" - \{id}")
}
println("commands:")
println(" - m5-digest --seed N")
println(" - m6-segment --seed N")
println(" - k1-partition-heal --seed N")
println(" - l3f-switched-fabric --seed N")
println(" - l3g-switched-fabric-qos-irt --seed N")
println(" - d57-link-readiness --seed N")
println(" - cl7-pcapng-hex --seed N")
println(" - npcap-list-ifaces")
println(" - raw-socket-list-ifaces")
println(" - udp-loopback-smoke --timeout-ms N")
println(
" - raw-socket-smoke --iface NAME --allow-send --allow-capture --timeout-ms N --attempts N [--ethertype HEX] [--dst-mac HEX] [--src-mac HEX] [--payload-hex HEX]",
)
println(
" - raw-socket-roundtrip-pcap --iface NAME --out PATH --allow-send --allow-capture --timeout-ms N --attempts N [--ethertype HEX] [--dst-mac HEX] [--src-mac HEX] [--payload-hex HEX]",
)
println(" - npcap-live-smoke --iface NAME --timeout-ms N [--filter EXPR]")
println(
" - npcap-send-smoke --iface NAME --allow-send --timeout-ms N [--ethertype HEX] [--dst-mac HEX] [--src-mac HEX] [--payload-hex HEX]",
)
println(
" - npcap-roundtrip-smoke --iface NAME --allow-send --allow-capture --timeout-ms N --attempts N [--filter EXPR] [--ethertype HEX] [--dst-mac HEX] [--src-mac HEX] [--payload-hex HEX]",
)
println(
" - npcap-roundtrip-pcap --iface NAME --out PATH --allow-send --allow-capture --timeout-ms N --attempts N [--filter EXPR] [--ethertype HEX] [--dst-mac HEX] [--src-mac HEX] [--payload-hex HEX]",
)
println(
" - npcap-capture-pcap --iface NAME --out PATH --allow-capture --timeout-ms N [--filter EXPR]",
)
println(
" - npcap-capture-frame-pool --iface NAME --allow-capture --timeout-ms N [--filter EXPR]",
)
}
///|
fn parse_seed(args : Array[String], default~ : Int) -> Int {
for i in 0.. String {
for i in 0.. Int {
for i in 0.. Bytes {
@lib.native_make_ethernet_smoke_frame(
ethertype=parse_hex_u16_option(args, "--ethertype", default=0x88b5),
dst_mac=parse_hex_bytes_option(args, "--dst-mac", default=b""),
src_mac=parse_hex_bytes_option(args, "--src-mac", default=b""),
payload=parse_hex_bytes_option(args, "--payload-hex", default=b""),
)
}
///|
fn parse_hex_u16_option(
args : Array[String],
name : String,
default~ : Int,
) -> Int {
let text = parse_text_option(args, name, default="")
if text == "" {
default
} else {
parse_hex_u16(text, default~)
}
}
///|
fn parse_hex_bytes_option(
args : Array[String],
name : String,
default~ : Bytes,
) -> Bytes {
let text = parse_text_option(args, name, default="")
if text == "" {
default
} else {
parse_hex_bytes(text, default~)
}
}
///|
fn parse_hex_u16(text : String, default~ : Int) -> Int {
let bytes = @utf8.encode(text)
let start = if bytes.length() >= 2 &&
bytes[0] == b'0' &&
(bytes[1] == b'x' || bytes[1] == b'X') {
2
} else {
0
}
let mut value = 0
let mut seen = false
for i in start.. 0xffff {
return default
}
}
}
if seen {
value
} else {
default
}
}
///|
fn parse_hex_bytes(text : String, default~ : Bytes) -> Bytes {
let bytes = @utf8.encode(text)
let out : Array[Byte] = []
let mut high = -1
for byte in bytes {
if !is_hex_separator(byte) {
let digit = hex_value(byte)
if digit < 0 {
return default
}
if high < 0 {
high = digit
} else {
out.push(((high << 4) | digit).to_byte())
high = -1
}
}
}
if high >= 0 {
default
} else {
Bytes::from_array(out)
}
}
///|
fn is_hex_separator(byte : Byte) -> Bool {
byte == b':' || byte == b'-' || byte == b'_' || byte == b' '
}
///|
fn hex_value(byte : Byte) -> Int {
if byte >= b'0' && byte <= b'9' {
byte.to_int() - b'0'.to_int()
} else if byte >= b'a' && byte <= b'f' {
byte.to_int() - b'a'.to_int() + 10
} else if byte >= b'A' && byte <= b'F' {
byte.to_int() - b'A'.to_int() + 10
} else {
-1
}
}
///|
fn has_flag(args : Array[String], name : String) -> Bool {
for arg in args {
if arg == name {
return true
}
}
false
}
///|
fn parse_positive_int(text : String, default~ : Int) -> Int {
if text == "" {
return default
}
let bytes = @utf8.encode(text)
let mut value = 0
for ch in bytes {
if ch < b'0' || ch > b'9' {
return default
}
value = value * 10 + ch.to_int() - b'0'.to_int()
}
value
}
///|
fn npcap_live_smoke_line(
report : @lib.NativeNpcapManualLiveSmokeReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
"npcap-live-smoke iface=\{iface} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} filter_attempted=\{bool_text(report.filter_attempted)} filter_configured=\{bool_text(report.filter_configured)} capture_attempted=\{bool_text(report.capture_attempted)} captured_bytes=\{report.captured_frame_bytes} closed=\{bool_text(report.closed)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_interface_list_text(
report : @lib.NativeNpcapInterfaceListReport,
) -> String {
let buf = StringBuilder::new()
buf.write_string("npcap-list-ifaces count=")
buf.write_string(report.interface_count.to_string())
buf.write_string(" runtime_available=")
buf.write_string(bool_text(report.npcap_runtime_available))
buf.write_string(" listing_supported=")
buf.write_string(bool_text(report.interface_listing_supported))
buf.write_string(" live_capture_evidence=")
buf.write_string(bool_text(report.live_capture_evidence))
buf.write_string(" label=")
buf.write_string(report.evidence_label)
for index, iface in report.interfaces {
buf.write_char('\n')
buf.write_string(index.to_string())
buf.write_char('\t')
buf.write_string(iface.name)
buf.write_char('\t')
buf.write_string(iface.description)
}
buf.to_string()
}
///|
fn raw_socket_interface_list_text(
report : @lib.NativeRawSocketInterfaceListReport,
) -> String {
let buf = StringBuilder::new()
buf.write_string("raw-socket-list-ifaces count=")
buf.write_string(report.interface_count.to_string())
buf.write_string(" surface_implemented=")
buf.write_string(bool_text(report.raw_socket_adapter_surface_implemented))
buf.write_string(" listing_supported=")
buf.write_string(bool_text(report.interface_listing_supported))
buf.write_string(" live_capture_evidence=")
buf.write_string(bool_text(report.live_capture_evidence))
buf.write_string(" label=")
buf.write_string(report.evidence_label)
for index, iface in report.interfaces {
buf.write_char('\n')
buf.write_string(index.to_string())
buf.write_char('\t')
buf.write_string(iface.name)
buf.write_char('\t')
buf.write_string(iface.description)
}
buf.to_string()
}
///|
fn udp_loopback_smoke_line(
report : @lib.NativeUdpLoopbackSmokeReport,
) -> String {
let local_evidence = report.loopback_smoke_passed && !report.live_nic_evidence
"udp-loopback-smoke native_backend_present=\{bool_text(report.native_backend_present)} udp_socket_adapter_implemented=\{bool_text(report.udp_socket_adapter_implemented)} loopback_smoke_passed=\{bool_text(report.loopback_smoke_passed)} timeout_is_benign=\{bool_text(report.timeout_is_benign)} local_loopback_evidence=\{bool_text(local_evidence)} live_nic_evidence=\{bool_text(report.live_nic_evidence)} bind_port=\{report.bind_port} sent_len=\{report.sent_len} received_len=\{report.received_len} payload_digest=\{report.payload_digest} label=\{report.evidence_label}"
}
///|
fn udp_loopback_smoke_failure_line(timeout_ms : Int) -> String {
ignore(timeout_ms)
let native_present = @lib.native_stub_version() > 0
"udp-loopback-smoke native_backend_present=\{bool_text(native_present)} udp_socket_adapter_implemented=\{bool_text(native_present)} loopback_smoke_passed=false timeout_is_benign=false local_loopback_evidence=false live_nic_evidence=false bind_port=-1 sent_len=0 received_len=0 payload_digest=0 last_error_code=\{@lib.native_last_error_code()} label=native.udp.loopback.local-smoke"
}
///|
fn raw_socket_smoke_line(
report : @lib.NativeRawSocketManualSmokeReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
"raw-socket-smoke iface=\{iface} allow_send=\{bool_text(report.manual_send_allowed)} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} send_attempted=\{bool_text(report.send_attempted)} sent_len=\{report.sent_len} frame_len=\{report.frame_len} frame_digest=\{report.frame_digest} capture_attempted=\{bool_text(report.capture_attempted)} attempts=\{report.capture_attempts} captured_bytes=\{report.captured_frame_bytes} matched=\{bool_text(report.captured_matches_sent_frame)} closed=\{bool_text(report.closed)} live_send_evidence=\{bool_text(report.live_send_evidence)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} live_roundtrip_evidence=\{bool_text(report.live_roundtrip_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn raw_socket_roundtrip_pcap_line(
report : @lib.NativeRawSocketRoundtripPcapArtifactReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
let out = if report.output_path == "" {
""
} else {
report.output_path
}
"raw-socket-roundtrip-pcap iface=\{iface} out=\{out} allow_send=\{bool_text(report.manual_send_allowed)} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} send_attempted=\{bool_text(report.send_attempted)} sent_len=\{report.sent_len} frame_len=\{report.frame_len} frame_digest=\{report.frame_digest} capture_attempted=\{bool_text(report.capture_attempted)} attempts=\{report.capture_attempts} captured_bytes=\{report.captured_frame_bytes} matched=\{bool_text(report.captured_matches_sent_frame)} pcap_write_attempted=\{bool_text(report.pcap_write_attempted)} pcap_written_len=\{report.pcap_written_len} artifact_evidence=\{bool_text(report.pcap_artifact_evidence)} closed=\{bool_text(report.closed)} live_send_evidence=\{bool_text(report.live_send_evidence)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} live_roundtrip_evidence=\{bool_text(report.live_roundtrip_evidence)} live_roundtrip_pcap_evidence=\{bool_text(report.live_roundtrip_pcap_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_send_smoke_line(
report : @lib.NativeNpcapManualSendSmokeReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
"npcap-send-smoke iface=\{iface} allow_send=\{bool_text(report.manual_send_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} send_attempted=\{bool_text(report.send_attempted)} sent_len=\{report.sent_len} frame_len=\{report.frame_len} frame_digest=\{report.frame_digest} closed=\{bool_text(report.closed)} live_send_evidence=\{bool_text(report.live_send_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_roundtrip_smoke_line(
report : @lib.NativeNpcapSendCaptureRoundtripReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
"npcap-roundtrip-smoke iface=\{iface} allow_send=\{bool_text(report.manual_send_allowed)} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} filter_attempted=\{bool_text(report.filter_attempted)} filter_configured=\{bool_text(report.filter_configured)} send_attempted=\{bool_text(report.send_attempted)} sent_len=\{report.sent_len} frame_len=\{report.frame_len} frame_digest=\{report.frame_digest} capture_attempted=\{bool_text(report.capture_attempted)} attempts=\{report.capture_attempts} captured_bytes=\{report.captured_frame_bytes} matched=\{bool_text(report.captured_matches_sent_frame)} closed=\{bool_text(report.closed)} live_send_evidence=\{bool_text(report.live_send_evidence)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} live_roundtrip_evidence=\{bool_text(report.live_roundtrip_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_roundtrip_pcap_line(
report : @lib.NativeNpcapRoundtripPcapArtifactReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
let out = if report.output_path == "" {
""
} else {
report.output_path
}
"npcap-roundtrip-pcap iface=\{iface} out=\{out} allow_send=\{bool_text(report.manual_send_allowed)} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} filter_attempted=\{bool_text(report.filter_attempted)} filter_configured=\{bool_text(report.filter_configured)} send_attempted=\{bool_text(report.send_attempted)} sent_len=\{report.sent_len} frame_len=\{report.frame_len} frame_digest=\{report.frame_digest} capture_attempted=\{bool_text(report.capture_attempted)} attempts=\{report.capture_attempts} captured_bytes=\{report.captured_frame_bytes} matched=\{bool_text(report.captured_matches_sent_frame)} pcap_write_attempted=\{bool_text(report.pcap_write_attempted)} pcap_written_len=\{report.pcap_written_len} artifact_evidence=\{bool_text(report.pcap_artifact_evidence)} closed=\{bool_text(report.closed)} live_roundtrip_evidence=\{bool_text(report.live_roundtrip_evidence)} live_roundtrip_pcap_evidence=\{bool_text(report.live_roundtrip_pcap_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_capture_pcap_line(
report : @lib.NativeNpcapCapturePcapArtifactReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
let out = if report.output_path == "" {
""
} else {
report.output_path
}
"npcap-capture-pcap iface=\{iface} out=\{out} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} filter_attempted=\{bool_text(report.filter_attempted)} filter_configured=\{bool_text(report.filter_configured)} capture_attempted=\{bool_text(report.capture_attempted)} captured_bytes=\{report.captured_frame_bytes} pcap_write_attempted=\{bool_text(report.pcap_write_attempted)} pcap_written_len=\{report.pcap_written_len} artifact_evidence=\{bool_text(report.pcap_artifact_evidence)} closed=\{bool_text(report.closed)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn npcap_capture_frame_pool_line(
report : @lib.NativeNpcapFramePoolCaptureReport,
) -> String {
let iface = if report.interface_name == "" {
""
} else {
report.interface_name
}
"npcap-capture-frame-pool iface=\{iface} allow_capture=\{bool_text(report.manual_capture_allowed)} attempted_open=\{bool_text(report.attempted_open)} opened=\{bool_text(report.opened)} filter_attempted=\{bool_text(report.filter_attempted)} filter_configured=\{bool_text(report.filter_configured)} capture_attempted=\{bool_text(report.capture_attempted)} captured_bytes=\{report.captured_frame_bytes} frame_pool_attempted=\{bool_text(report.frame_pool_attempted)} frame_pool_written_len=\{report.frame_pool_written_len} frame_pool_read_len=\{report.frame_pool_read_len} frame_pool_evidence=\{bool_text(report.frame_pool_capture_evidence)} closed=\{bool_text(report.closed)} live_capture_evidence=\{bool_text(report.live_capture_evidence)} live_frame_pool_evidence=\{bool_text(report.live_frame_pool_evidence)} last_error_code=\{report.last_error_code} label=\{report.evidence_label}"
}
///|
fn bool_text(value : Bool) -> String {
if value {
"true"
} else {
"false"
}
}
///|
fn bytes_to_hex(bytes : Bytes) -> String {
let buf = StringBuilder::new()
for byte in bytes {
let value = byte.to_int()
buf.write_char(hex_digit(value / 16))
buf.write_char(hex_digit(value % 16))
}
buf.to_string()
}
///|
fn hex_digit(value : Int) -> Char {
if value < 10 {
(b'0'.to_int() + value).to_byte().to_char()
} else {
(b'a'.to_int() + value - 10).to_byte().to_char()
}
}