1use std::sync::Arc;
8
9use serde_json::Value as JsonValue;
10use sim_codec::{
11 CodecDefaultDecode, CodecRuntime, DecodeBudget, Decoder, Encoder, Input, LocatedDecoder,
12 LocatedEncoder, Output, ReadCx, TreeDecoder, TreeEncoder, codec_value, validate_expr_tree,
13};
14use sim_kernel::{
15 AbiVersion, DefaultFactory, Dependency, Error, Export, Expr, Lib, LibManifest, LibTarget,
16 Linker, LocatedExpr, LocatedExprTree, Result, Symbol, Version, WriteCx,
17};
18
19use crate::{
20 expr_to_json, json_to_expr, json_to_located_expr, json_to_tree, located_expr_to_json,
21 tree_to_json,
22};
23
24pub struct JsonCodec;
32
33impl Decoder for JsonCodec {
34 fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<Expr> {
35 let source = input.into_string()?;
36 let mut budget = DecodeBudget::new(cx.limits);
37 budget.check_input_bytes(cx.codec, source.len())?;
38 let value =
39 serde_json::from_str::<JsonValue>(&source).map_err(|err| Error::CodecError {
40 codec: cx.codec,
41 message: err.to_string(),
42 })?;
43 json_to_expr(cx.codec, &value, &mut budget, 0)
44 }
45}
46
47impl Encoder for JsonCodec {
48 fn encode(&self, cx: &mut WriteCx<'_>, expr: &Expr) -> Result<Output> {
49 let value = expr_to_json(expr);
50 let text = serde_json::to_string(&value).map_err(|err| Error::CodecError {
51 codec: cx.codec,
52 message: err.to_string(),
53 })?;
54 Ok(Output::Text(text))
55 }
56}
57
58impl LocatedDecoder for JsonCodec {
59 fn decode_located(
60 &self,
61 cx: &mut ReadCx<'_>,
62 input: Input,
63 _source_id: String,
64 ) -> Result<LocatedExpr> {
65 let source = input.into_string()?;
66 let mut budget = DecodeBudget::new(cx.limits);
67 budget.check_input_bytes(cx.codec, source.len())?;
68 let value =
69 serde_json::from_str::<JsonValue>(&source).map_err(|err| Error::CodecError {
70 codec: cx.codec,
71 message: err.to_string(),
72 })?;
73 json_to_located_expr(cx.codec, &value, &mut budget, 0)
74 }
75}
76
77impl LocatedEncoder for JsonCodec {
78 fn encode_located(&self, cx: &mut WriteCx<'_>, expr: &LocatedExpr) -> Result<Output> {
79 let value = located_expr_to_json(expr, cx.options.lossless_origin);
80 let text = serde_json::to_string(&value).map_err(|err| Error::CodecError {
81 codec: cx.codec,
82 message: err.to_string(),
83 })?;
84 Ok(Output::Text(text))
85 }
86}
87
88impl TreeDecoder for JsonCodec {
89 fn decode_tree(
90 &self,
91 cx: &mut ReadCx<'_>,
92 input: Input,
93 _source_id: String,
94 ) -> Result<LocatedExprTree> {
95 let source = input.into_string()?;
96 let mut budget = DecodeBudget::new(cx.limits);
97 budget.check_input_bytes(cx.codec, source.len())?;
98 let value =
99 serde_json::from_str::<JsonValue>(&source).map_err(|err| Error::CodecError {
100 codec: cx.codec,
101 message: err.to_string(),
102 })?;
103 json_to_tree(cx.codec, &value, &mut budget, 0)
104 }
105}
106
107impl TreeEncoder for JsonCodec {
108 fn encode_tree(&self, cx: &mut WriteCx<'_>, expr: &LocatedExprTree) -> Result<Output> {
109 validate_expr_tree(cx.codec, expr)?;
110 let value = tree_to_json(expr, cx.options.lossless_origin);
111 let text = serde_json::to_string(&value).map_err(|err| Error::CodecError {
112 codec: cx.codec,
113 message: err.to_string(),
114 })?;
115 Ok(Output::Text(text))
116 }
117}
118
119pub struct JsonCodecLib {
124 symbol: Symbol,
125 codec_id: sim_kernel::CodecId,
126}
127
128impl JsonCodecLib {
129 pub fn new(id: sim_kernel::CodecId) -> Self {
131 Self {
132 symbol: Symbol::qualified("codec", "json"),
133 codec_id: id,
134 }
135 }
136}
137
138impl Lib for JsonCodecLib {
139 fn manifest(&self) -> LibManifest {
140 LibManifest {
141 id: self.symbol.clone(),
142 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
143 abi: AbiVersion { major: 0, minor: 1 },
144 target: LibTarget::HostRegistered,
145 requires: Vec::<Dependency>::new(),
146 capabilities: Vec::new(),
147 exports: vec![Export::Codec {
148 symbol: self.symbol.clone(),
149 codec_id: Some(self.codec_id),
150 }],
151 }
152 }
153
154 fn load(&self, _cx: &mut sim_kernel::LoadCx, linker: &mut Linker) -> Result<()> {
155 let _factory = DefaultFactory;
156 let expr_shape =
157 sim_codec::resolve_expr_shape(linker, &Symbol::qualified("codec", "JsonTaggedExpr"))?;
158 let options_shape = sim_codec::resolve_options_shape(linker)?;
159
160 linker.codec_value(
161 self.symbol.clone(),
162 codec_value(CodecRuntime {
163 id: self.codec_id,
164 symbol: self.symbol.clone(),
165 decoder: Some(Arc::new(JsonCodec)),
166 located_decoder: Some(Arc::new(JsonCodec)),
167 tree_decoder: Some(Arc::new(JsonCodec)),
168 encoder: Some(Arc::new(JsonCodec)),
169 located_encoder: Some(Arc::new(JsonCodec)),
170 tree_encoder: Some(Arc::new(JsonCodec)),
171 expr_shape,
172 options_shape,
173 default_decode: CodecDefaultDecode::Datum,
174 }),
175 )?;
176 Ok(())
177 }
178}