sim_codec_chat/
canonical.rs1use 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
17pub 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
38pub struct ChatCodecLib {
41 symbol: Symbol,
42 codec_id: CodecId,
43}
44
45impl ChatCodecLib {
46 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}