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