sim_codec_bitwise_base64/
codec.rs1use std::sync::Arc;
8
9use sim_codec::{
10 CodecDefaultDecode, CodecRuntime, Decoder, Encoder, Input, LocatedDecoder, LocatedEncoder,
11 Output, ReadCx, TreeDecoder, TreeEncoder, codec_value, validate_expr_tree,
12};
13use sim_codec_binary_base64::{decode_base64_with_limits, encode_base64};
14use sim_kernel::{
15 AbiVersion, CodecId, DefaultFactory, Dependency, Error, Export, Expr, Lib, LibManifest,
16 LibTarget, Linker, LocatedExpr, LocatedExprTree, Result, Symbol, Version, WriteCx,
17};
18
19use crate::cookbook::{BitwiseBase64RoundtripReport, roundtrip_report_symbol};
20
21pub struct BitwiseBase64Codec;
30
31impl Decoder for BitwiseBase64Codec {
32 fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<Expr> {
33 decode_tree(cx, input).map(|tree| tree.located().expr)
34 }
35}
36
37impl Encoder for BitwiseBase64Codec {
38 fn encode(&self, _cx: &mut WriteCx<'_>, expr: &Expr) -> Result<Output> {
39 let frame = sim_codec_bitwise::encode_frame(expr)?;
40 Ok(Output::Text(encode_base64(&frame.0)))
41 }
42}
43
44impl LocatedDecoder for BitwiseBase64Codec {
45 fn decode_located(
46 &self,
47 cx: &mut ReadCx<'_>,
48 input: Input,
49 _source_id: String,
50 ) -> Result<LocatedExpr> {
51 decode_tree(cx, input).map(|tree| tree.located())
52 }
53}
54
55impl LocatedEncoder for BitwiseBase64Codec {
56 fn encode_located(&self, cx: &mut WriteCx<'_>, expr: &LocatedExpr) -> Result<Output> {
57 let frame = sim_codec_bitwise::encode_located_frame(expr, cx.options.lossless_origin)?;
58 Ok(Output::Text(encode_base64(&frame.0)))
59 }
60}
61
62impl TreeDecoder for BitwiseBase64Codec {
63 fn decode_tree(
64 &self,
65 cx: &mut ReadCx<'_>,
66 input: Input,
67 _source_id: String,
68 ) -> Result<LocatedExprTree> {
69 decode_tree(cx, input)
70 }
71}
72
73impl TreeEncoder for BitwiseBase64Codec {
74 fn encode_tree(&self, cx: &mut WriteCx<'_>, expr: &LocatedExprTree) -> Result<Output> {
75 validate_expr_tree(cx.codec, expr)?;
76 let frame = sim_codec_bitwise::encode_located_tree_frame(expr, cx.options.lossless_origin)?;
77 Ok(Output::Text(encode_base64(&frame.0)))
78 }
79}
80
81fn decode_tree(cx: &mut ReadCx<'_>, input: Input) -> Result<LocatedExprTree> {
82 let text = input_text(cx.codec, input)?;
83 let bytes = decode_base64_with_limits(cx.codec, &text, cx.limits)?;
84 sim_codec_bitwise::decode_located_tree_frame_with_limits(
85 cx.codec,
86 &bytes,
87 sim_codec_bitwise::DecodeLimits::from(cx.limits),
88 )
89 .map(|(_, tree)| tree)
90}
91
92fn input_text(codec: CodecId, input: Input) -> Result<String> {
93 match input {
94 Input::Text(text) => Ok(text),
95 Input::Bytes(bytes) => String::from_utf8(bytes).map_err(|err| Error::CodecError {
96 codec,
97 message: format!("bitwise-base64 input is not valid UTF-8: {err}"),
98 }),
99 }
100}
101
102pub struct BitwiseBase64CodecLib {
108 symbol: Symbol,
109 codec_id: CodecId,
110}
111
112impl BitwiseBase64CodecLib {
113 pub fn new(id: CodecId) -> Self {
116 Self {
117 symbol: Symbol::qualified("codec", "bitwise-base64"),
118 codec_id: id,
119 }
120 }
121}
122
123impl Lib for BitwiseBase64CodecLib {
124 fn manifest(&self) -> LibManifest {
125 LibManifest {
126 id: self.symbol.clone(),
127 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
128 abi: AbiVersion { major: 0, minor: 1 },
129 target: LibTarget::HostRegistered,
130 requires: Vec::<Dependency>::new(),
131 capabilities: Vec::new(),
132 exports: vec![
133 Export::Codec {
134 symbol: self.symbol.clone(),
135 codec_id: Some(self.codec_id),
136 },
137 Export::Function {
138 symbol: roundtrip_report_symbol(),
139 function_id: None,
140 },
141 ],
142 }
143 }
144
145 fn load(&self, cx: &mut sim_kernel::LoadCx, linker: &mut Linker) -> Result<()> {
146 let _factory = DefaultFactory;
147 let expr_shape = sim_codec::resolve_expr_shape(
148 linker,
149 &Symbol::qualified("codec", "BitwiseBase64Text"),
150 )?;
151 let options_shape = sim_codec::resolve_options_shape(linker)?;
152
153 linker.codec_value(
154 self.symbol.clone(),
155 codec_value(CodecRuntime {
156 id: self.codec_id,
157 symbol: self.symbol.clone(),
158 decoder: Some(Arc::new(BitwiseBase64Codec)),
159 located_decoder: Some(Arc::new(BitwiseBase64Codec)),
160 tree_decoder: Some(Arc::new(BitwiseBase64Codec)),
161 encoder: Some(Arc::new(BitwiseBase64Codec)),
162 located_encoder: Some(Arc::new(BitwiseBase64Codec)),
163 tree_encoder: Some(Arc::new(BitwiseBase64Codec)),
164 expr_shape,
165 options_shape,
166 default_decode: CodecDefaultDecode::Datum,
167 }),
168 )?;
169 linker.function_value(
170 roundtrip_report_symbol(),
171 cx.factory()
172 .opaque(Arc::new(BitwiseBase64RoundtripReport))?,
173 )?;
174 Ok(())
175 }
176}