use sim_codec_binary_base64::{decode_base64_with_limits, encode_base64};
use sim_kernel::{Args, Callable, Cx, Error, Expr, Object, ObjectCompat, Result, Symbol, Value};
use sim_value::build::entry as field;
pub(crate) fn roundtrip_report_symbol() -> Symbol {
Symbol::qualified("bitwise-base64", "roundtrip-report")
}
pub(crate) struct BitwiseBase64RoundtripReport;
impl Callable for BitwiseBase64RoundtripReport {
fn call(&self, cx: &mut Cx, args: Args) -> Result<Value> {
if !args.values().is_empty() {
return Err(Error::Eval(format!(
"{} expects no arguments",
roundtrip_report_symbol()
)));
}
let sample = sample_expr();
let frame = sim_codec_bitwise::encode_frame(&sample)?;
let text = encode_base64(&frame.0);
let bytes = decode_base64_with_limits(
sim_kernel::CodecId(0),
&text,
sim_codec::DecodeLimits::default(),
)?;
let (_, decoded) = sim_codec_bitwise::decode_frame(sim_kernel::CodecId(0), &bytes)?;
let report = Expr::Map(vec![
field(
"kind",
Expr::Symbol(Symbol::qualified("codec", "roundtrip")),
),
field("codec", Expr::String("codec/bitwise-base64".to_owned())),
field("wire", Expr::String("base64 text over vbits".to_owned())),
field("encoded-chars", Expr::String(text.len().to_string())),
field("decoded", decoded.clone()),
field("roundtrip", Expr::Bool(decoded.canonical_eq(&sample))),
field(
"lanes",
Expr::List(vec![
Expr::String("encode".to_owned()),
Expr::String("decode".to_owned()),
]),
),
]);
cx.factory().expr(report)
}
}
impl Object for BitwiseBase64RoundtripReport {
fn display(&self, _cx: &mut Cx) -> Result<String> {
Ok(roundtrip_report_symbol().to_string())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl ObjectCompat for BitwiseBase64RoundtripReport {
fn as_callable(&self) -> Option<&dyn Callable> {
Some(self)
}
}
fn sample_expr() -> Expr {
Expr::List(vec![
Expr::Symbol(Symbol::qualified("codec", "bitwise-base64-demo")),
Expr::String("text wrapper".to_owned()),
Expr::Bool(true),
])
}