use sim_codec::{
CodecPrism, Input, Output, PrismDiagnostic, PrismOutput, RuntimeCodecPrism, decode_with_codec,
encode_with_codec,
};
use sim_kernel::{Cx, EncodeOptions, EncodePosition, Expr, ReadPolicy, Symbol};
use sim_lib_scene::{data_map, node, sym};
pub const MULTI_CODEC_LENS: &str = "view:codec-multi";
pub const SYSEX_COMPARISON_LENS: &str = "view:codec-sysex-comparison";
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProbeResult {
pub encoded: String,
pub lossless: bool,
pub semantic_identity: bool,
pub semantic_id: Option<String>,
pub span_count: usize,
pub diagnostics: Vec<String>,
pub trusted_executable: bool,
pub alternates: Vec<Symbol>,
}
impl ProbeResult {
pub fn lossless(encoded: impl Into<String>) -> Self {
Self {
encoded: encoded.into(),
lossless: true,
semantic_identity: true,
semantic_id: None,
span_count: 0,
diagnostics: Vec::new(),
trusted_executable: false,
alternates: Vec::new(),
}
}
}
pub fn roundtrip_probe(cx: &mut Cx, codec: &Symbol, value: &Expr) -> ProbeResult {
match encode_with_codec(cx, codec, value, EncodeOptions::default()) {
Ok(output) => {
let (encoded, input, prism_output) = render_output(output);
let decoded_lossless = decode_with_codec(cx, codec, input, ReadPolicy::default())
.map(|decoded| decoded.canonical_eq(value))
.unwrap_or(false);
let prism = prism_for_codec(codec);
let proof = match prism_output {
PrismOutput::Text(text) => prism.round_trip(cx, &text, EncodePosition::Data),
PrismOutput::Bytes(bytes) => {
prism.round_trip_bytes(cx, &bytes, EncodePosition::Data)
}
};
let semantic_identity = proof.loss_report.semantic_identity;
let diagnostics = diagnostic_text(&proof.loss_report.diagnostics);
ProbeResult {
encoded,
lossless: decoded_lossless && proof.loss_report.lossless,
semantic_identity,
semantic_id: proof.parse.semantic_id.as_ref().map(|id| id.stable.clone()),
span_count: proof.parse.span_map.len(),
diagnostics,
trusted_executable: proof.parse.inspection.trusted_executable,
alternates: suggested_alternates(codec),
}
}
Err(error) => ProbeResult {
encoded: format!("<encode error: {error}>"),
lossless: false,
semantic_identity: false,
semantic_id: None,
span_count: 0,
diagnostics: vec![format!("encode-error: {error}")],
trusted_executable: false,
alternates: suggested_alternates(codec),
},
}
}
fn render_output(output: Output) -> (String, Input, PrismOutput) {
match output {
Output::Text(text) => (
text.clone(),
Input::Text(text.clone()),
PrismOutput::Text(text),
),
Output::Bytes(bytes) => {
let hex: String = bytes.iter().map(|byte| format!("{byte:02x}")).collect();
let display = format!("{} bytes: {hex}", bytes.len());
(
display,
Input::Bytes(bytes.clone()),
PrismOutput::Bytes(bytes),
)
}
}
}
fn prism_for_codec(codec: &Symbol) -> RuntimeCodecPrism {
match (&codec.namespace, &*codec.name) {
(Some(namespace), "chat") if &**namespace == "codec" => {
RuntimeCodecPrism::domain(codec.clone(), "chat transcript")
}
(Some(namespace), "mcp") if &**namespace == "codec" => {
RuntimeCodecPrism::domain(codec.clone(), "MCP envelope")
}
(Some(namespace), "binary") if &**namespace == "codec" => {
RuntimeCodecPrism::binary(codec.clone())
}
(Some(namespace), "binary-base64") if &**namespace == "codec" => {
RuntimeCodecPrism::binary_base64(codec.clone())
}
_ => RuntimeCodecPrism::general(codec.clone()),
}
}
fn suggested_alternates(codec: &Symbol) -> Vec<Symbol> {
let installed = ["lisp", "algol", "json", "binary", "binary-base64"];
installed
.iter()
.map(|name| Symbol::qualified("codec", *name))
.filter(|candidate| candidate != codec)
.collect()
}
fn diagnostic_text(diagnostics: &[PrismDiagnostic]) -> Vec<String> {
diagnostics
.iter()
.map(|diagnostic| format!("{}: {}", diagnostic.code, diagnostic.message))
.collect()
}
pub fn multi_codec_view(cx: &mut Cx, codecs: &[Symbol], value: &Expr) -> Expr {
let panels = codecs
.iter()
.map(|codec| codec_panel(cx, codec, value))
.collect();
node(
"stack",
vec![
("role", sym("multi-codec")),
("dir", sym("row")),
("children", Expr::List(panels)),
],
)
}
pub fn sysex_comparison_view(hex: &str, bytes: &[u8], lisp: &str, probe: &ProbeResult) -> Expr {
let status = if probe.lossless { "ok" } else { "warn" };
node(
"stack",
vec![
("lens", Expr::Symbol(Symbol::new(SYSEX_COMPARISON_LENS))),
("role", sym("sysex-comparison-view")),
("dir", sym("column")),
(
"children",
Expr::List(vec![
node(
"table",
vec![
("role", sym("sysex-format-comparison")),
(
"rows",
Expr::List(vec![
comparison_row("hex", hex),
comparison_row("binary", &binary_display(bytes)),
comparison_row("lisp", lisp),
]),
),
],
),
node(
"badge",
vec![
("role", sym("round-trip-probe")),
("status", sym(status)),
("label", Expr::String(probe.encoded.clone())),
],
),
]),
),
],
)
}
fn codec_panel(cx: &mut Cx, codec: &Symbol, value: &Expr) -> Expr {
let probe = roundtrip_probe(cx, codec, value);
let prism_report = prism_report(&probe);
let badge = node(
"badge",
vec![
("status", sym(if probe.lossless { "ok" } else { "warn" })),
(
"label",
Expr::String(
if probe.lossless {
"round-trips"
} else {
"loss"
}
.to_owned(),
),
),
],
);
let inner = node(
"box",
vec![
("role", sym("codec-prism")),
(
"prism",
data_map(vec![
(
"semantic-id",
Expr::String(probe.semantic_id.clone().unwrap_or_default()),
),
("semantic-identity", bool_expr(probe.semantic_identity)),
("span-count", int_expr(probe.span_count)),
("trusted-executable", bool_expr(probe.trusted_executable)),
(
"alternates",
Expr::List(probe.alternates.iter().cloned().map(Expr::Symbol).collect()),
),
]),
),
(
"children",
Expr::List(vec![
node("text", vec![("text", Expr::String(codec.to_string()))]),
badge,
prism_report,
node(
"field",
vec![
("datatype", sym("text")),
("value", Expr::String(probe.encoded)),
],
),
]),
),
],
);
node(
"embed",
vec![("lens", Expr::Symbol(codec.clone())), ("scene", inner)],
)
}
fn prism_report(probe: &ProbeResult) -> Expr {
node(
"stack",
vec![
("role", sym("prism-diagnostics")),
("dir", sym("column")),
(
"children",
Expr::List(vec![
node(
"badge",
vec![
("role", sym("prism-loss-report")),
("status", sym(if probe.lossless { "ok" } else { "warn" })),
(
"label",
Expr::String(
if probe.semantic_identity {
"semantic identity"
} else {
"semantic loss"
}
.to_owned(),
),
),
],
),
data_map(vec![
("spans", int_expr(probe.span_count)),
(
"diagnostics",
Expr::List(
probe
.diagnostics
.iter()
.cloned()
.map(Expr::String)
.collect(),
),
),
]),
]),
),
],
)
}
fn bool_expr(value: bool) -> Expr {
Expr::Symbol(Symbol::new(if value { "true" } else { "false" }))
}
fn int_expr(value: usize) -> Expr {
Expr::String(value.to_string())
}
fn comparison_row(format: &str, value: &str) -> Expr {
data_map(vec![
("format", Expr::Symbol(Symbol::new(format))),
("value", Expr::String(value.to_owned())),
])
}
fn binary_display(bytes: &[u8]) -> String {
bytes
.iter()
.map(|byte| format!("{byte:08b}"))
.collect::<Vec<_>>()
.join(" ")
}