Skip to main content

sim_codec_chat/
canonical.rs

1//! The `codec:chat` decoder/encoder pair and its host-registered lib. Decodes
2//! the canonical `SIMCHAT1` transcript text into checked `Expr` and encodes
3//! checked transcripts back out, validating the transcript shape on both sides.
4
5use std::sync::Arc;
6
7use sim_codec::{
8    DecodeBudget, Decoder, DomainCodecLib, Encoder, Input, Output, ReadCx, domain_input_text,
9};
10use sim_kernel::{CodecId, Lib, LibManifest, Linker, LoadCx, Result, Symbol, WriteCx};
11
12use crate::{
13    expr::{decode_chat_text, encode_chat_text},
14    validate_chat_transcript,
15};
16
17/// Provider-neutral transcript codec.
18pub struct ChatCodec;
19
20impl Decoder for ChatCodec {
21    fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<sim_kernel::Expr> {
22        let source = domain_input_text(cx.codec, input)?;
23        let mut budget = DecodeBudget::new(cx.limits);
24        budget.check_input_bytes(cx.codec, source.len())?;
25        let expr = decode_chat_text(cx.codec, &source, &mut budget)?;
26        validate_chat_transcript(&expr)?;
27        Ok(expr)
28    }
29}
30
31impl Encoder for ChatCodec {
32    fn encode(&self, _cx: &mut WriteCx<'_>, expr: &sim_kernel::Expr) -> Result<Output> {
33        validate_chat_transcript(expr)?;
34        Ok(Output::Text(encode_chat_text(expr)))
35    }
36}
37
38/// Host-registered lib for `codec:chat`, built on the shared
39/// [`DomainCodecLib`] scaffold.
40pub struct ChatCodecLib {
41    symbol: Symbol,
42    codec_id: CodecId,
43}
44
45impl ChatCodecLib {
46    /// Creates the lib bound to the given runtime-assigned codec id.
47    pub fn new(id: CodecId) -> Self {
48        Self {
49            symbol: Symbol::qualified("codec", "chat"),
50            codec_id: id,
51        }
52    }
53
54    fn domain_lib(&self) -> DomainCodecLib {
55        DomainCodecLib::new(
56            self.symbol.clone(),
57            self.codec_id,
58            Arc::new(ChatCodec),
59            Arc::new(ChatCodec),
60            Symbol::qualified("codec", "ChatTranscript"),
61        )
62    }
63}
64
65impl Lib for ChatCodecLib {
66    fn manifest(&self) -> LibManifest {
67        self.domain_lib().manifest()
68    }
69
70    fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
71        self.domain_lib().load(cx, linker)
72    }
73}