Skip to main content

sim_codec_bridge/
canonical.rs

1use std::sync::Arc;
2
3use sim_codec::{
4    DecodeBudget, Decoder, DomainCodecLib, Encoder, Input, Output, ReadCx, domain_input_text,
5};
6use sim_kernel::{CodecId, Error, Expr, Lib, LibManifest, Linker, LoadCx, Result, Symbol, WriteCx};
7
8use crate::{BridgeBook, decode_bridge_text, encode_bridge_text, expr_to_packet, packet_to_expr};
9
10/// The `codec:bridge` decoder/encoder.
11pub struct BridgeCodec;
12
13impl Decoder for BridgeCodec {
14    fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<Expr> {
15        let source = domain_input_text(cx.codec, input)?;
16        let budget = DecodeBudget::new(cx.limits);
17        budget.check_input_bytes(cx.codec, source.len())?;
18        let packet = decode_bridge_text(&source, &BridgeBook::standard()).map_err(|err| {
19            Error::CodecError {
20                codec: cx.codec,
21                message: err.to_string(),
22            }
23        })?;
24        Ok(packet_to_expr(&packet))
25    }
26}
27
28impl Encoder for BridgeCodec {
29    fn encode(&self, cx: &mut WriteCx<'_>, expr: &Expr) -> Result<Output> {
30        let packet = expr_to_packet(expr).map_err(|err| Error::CodecError {
31            codec: cx.codec,
32            message: err.to_string(),
33        })?;
34        encode_bridge_text(&packet, &BridgeBook::standard())
35            .map(Output::Text)
36            .map_err(|err| Error::CodecError {
37                codec: cx.codec,
38                message: err.to_string(),
39            })
40    }
41}
42
43/// Host-registered lib that installs [`BridgeCodec`] as `codec:bridge`.
44pub struct BridgeCodecLib {
45    symbol: Symbol,
46    codec_id: CodecId,
47}
48
49impl BridgeCodecLib {
50    /// Creates a bridge codec lib for the given codec id.
51    pub fn new(id: CodecId) -> Self {
52        Self {
53            symbol: Symbol::qualified("codec", "bridge"),
54            codec_id: id,
55        }
56    }
57
58    fn domain_lib(&self) -> DomainCodecLib {
59        DomainCodecLib::new(
60            self.symbol.clone(),
61            self.codec_id,
62            Arc::new(BridgeCodec),
63            Arc::new(BridgeCodec),
64            crate::bridge_packet_shape_symbol(),
65        )
66    }
67}
68
69impl Lib for BridgeCodecLib {
70    fn manifest(&self) -> LibManifest {
71        self.domain_lib().manifest()
72    }
73
74    fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
75        self.domain_lib().load(cx, linker)
76    }
77}