1use std::io::{Read, Write};
2
3use mcproto_codec::{
4 error::{CodecError, CodecKind, CodecOperation, InvalidEncodingReason},
5 io::{read_exact_counted, write_all_counted},
6 varint::{VarIntRead, VarIntWrite},
7};
8use serde::{Deserialize, Serialize};
9
10use crate::{TypeCodec, component::JsonComponent};
11
12pub use serde_json::Value as JsonValue;
13
14#[derive(Debug, Clone, PartialEq)]
16pub struct JsonTextComponent(pub JsonComponent);
17
18impl JsonTextComponent {
19 pub const MAX_DECODE_UTF16_CODE_UNITS: usize = 262_144;
20 pub const MAX_DECODE_BYTES: usize = Self::MAX_DECODE_UTF16_CODE_UNITS * 3;
21 pub const MAX_DECODE_ENCODED_BYTES: usize = Self::MAX_DECODE_BYTES + 3;
22
23 pub const MAX_ENCODE_UTF16_CODE_UNITS: usize = 32_767;
25 pub const MAX_ENCODE_BYTES: usize = Self::MAX_ENCODE_UTF16_CODE_UNITS * 3;
26 pub const MAX_ENCODE_ENCODED_BYTES: usize = Self::MAX_ENCODE_BYTES + 3;
27
28 const MAX_COMPONENT_DEPTH: usize = 512;
29
30 pub fn text(value: impl Into<String>) -> Self {
31 Self(JsonComponent::text(value))
32 }
33
34 pub fn from_json_str(value: &str) -> Result<Self, serde_json::Error> {
35 let component = deserialize_json(value)?;
36 validate_component(&component).map_err(json_validation_error)?;
37 Ok(Self(component))
38 }
39
40 fn validate_length(
41 value: &str,
42 max_code_units: usize,
43 max_bytes: usize,
44 operation: CodecOperation,
45 bytes_processed: usize,
46 ) -> Result<(), CodecError> {
47 if value.len() > max_bytes {
48 return Err(CodecError::invalid_encoding_for_operation(
49 CodecKind::JsonTextComponent,
50 operation,
51 bytes_processed,
52 InvalidEncodingReason::StringTooLong { max_bytes },
53 ));
54 }
55 if value.encode_utf16().count() > max_code_units {
56 return Err(CodecError::invalid_encoding_for_operation(
57 CodecKind::JsonTextComponent,
58 operation,
59 bytes_processed,
60 InvalidEncodingReason::TooManyUtf16CodeUnits { max_code_units },
61 ));
62 }
63 Ok(())
64 }
65
66 fn invalid_json(
67 operation: CodecOperation,
68 bytes_processed: usize,
69 source: impl std::error::Error + Send + Sync + 'static,
70 ) -> CodecError {
71 CodecError::invalid_encoding_for_operation_with_source(
72 CodecKind::JsonTextComponent,
73 operation,
74 bytes_processed,
75 InvalidEncodingReason::InvalidJson,
76 source,
77 )
78 }
79}
80
81impl Default for JsonTextComponent {
82 fn default() -> Self {
83 Self::text("")
84 }
85}
86
87impl From<JsonComponent> for JsonTextComponent {
88 fn from(value: JsonComponent) -> Self {
89 Self(value)
90 }
91}
92
93impl From<String> for JsonTextComponent {
94 fn from(value: String) -> Self {
95 Self::text(value)
96 }
97}
98
99impl From<&str> for JsonTextComponent {
100 fn from(value: &str) -> Self {
101 Self::text(value)
102 }
103}
104
105impl TypeCodec for JsonTextComponent {
106 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
107 validate_component(&self.0)
108 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
109 let mut bytes = Vec::new();
110 let mut serializer = serde_json::Serializer::new(&mut bytes);
111 self.0
112 .serialize(serde_stacker::Serializer::new(&mut serializer))
113 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
114 let json = String::from_utf8(bytes)
115 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
116 Self::validate_length(
117 &json,
118 Self::MAX_ENCODE_UTF16_CODE_UNITS,
119 Self::MAX_ENCODE_BYTES,
120 CodecOperation::Write,
121 0,
122 )?;
123
124 let bytes = json.as_bytes();
125 let prefix_size = writer
126 .write_varint_with_size(bytes.len() as i32)
127 .map_err(|error| error.with_context(CodecKind::JsonTextComponent))?;
128 write_all_counted(writer, bytes, CodecKind::JsonTextComponent, prefix_size)
129 }
130
131 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
132 let (byte_length, prefix_size) = reader
133 .read_varint_with_size()
134 .map_err(|error| error.with_context(CodecKind::JsonTextComponent))?;
135 let byte_length = usize::try_from(byte_length).map_err(|_| {
136 CodecError::invalid_encoding(
137 CodecKind::JsonTextComponent,
138 prefix_size,
139 InvalidEncodingReason::NegativeLength { value: byte_length },
140 )
141 })?;
142 if byte_length > Self::MAX_DECODE_BYTES {
143 return Err(CodecError::invalid_encoding(
144 CodecKind::JsonTextComponent,
145 prefix_size,
146 InvalidEncodingReason::StringTooLong {
147 max_bytes: Self::MAX_DECODE_BYTES,
148 },
149 ));
150 }
151
152 let mut bytes = vec![0; byte_length];
153 read_exact_counted(
154 reader,
155 &mut bytes,
156 CodecKind::JsonTextComponent,
157 prefix_size,
158 )?;
159 let bytes_processed = prefix_size + byte_length;
160 let json = String::from_utf8(bytes).map_err(|error| {
161 let utf8_error = error.utf8_error();
162 CodecError::invalid_encoding(
163 CodecKind::JsonTextComponent,
164 bytes_processed,
165 InvalidEncodingReason::InvalidUtf8 {
166 valid_up_to: utf8_error.valid_up_to(),
167 error_len: utf8_error.error_len(),
168 },
169 )
170 })?;
171 Self::validate_length(
172 &json,
173 Self::MAX_DECODE_UTF16_CODE_UNITS,
174 Self::MAX_DECODE_BYTES,
175 CodecOperation::Read,
176 bytes_processed,
177 )?;
178
179 let component = deserialize_json(&json)
180 .map_err(|source| Self::invalid_json(CodecOperation::Read, bytes_processed, source))?;
181 validate_component(&component)
182 .map_err(|source| Self::invalid_json(CodecOperation::Read, bytes_processed, source))?;
183 Ok(Self(component))
184 }
185}
186
187fn deserialize_json(value: &str) -> Result<JsonComponent, serde_json::Error> {
188 validate_json_syntax_depth(value, JsonTextComponent::MAX_COMPONENT_DEPTH * 2 + 8)
189 .map_err(json_validation_error)?;
190 let mut deserializer = serde_json::Deserializer::from_str(value);
191 deserializer.disable_recursion_limit();
192 let component =
193 JsonComponent::deserialize(serde_stacker::Deserializer::new(&mut deserializer))?;
194 deserializer.end()?;
195 Ok(component)
196}
197
198fn validate_json_syntax_depth(value: &str, max_depth: usize) -> Result<(), JsonSyntaxDepthError> {
199 let mut depth = 0_usize;
200 let mut in_string = false;
201 let mut escaped = false;
202 for byte in value.bytes() {
203 if in_string {
204 if escaped {
205 escaped = false;
206 } else if byte == b'\\' {
207 escaped = true;
208 } else if byte == b'"' {
209 in_string = false;
210 }
211 continue;
212 }
213 match byte {
214 b'"' => in_string = true,
215 b'{' | b'[' => {
216 depth += 1;
217 if depth > max_depth {
218 return Err(JsonSyntaxDepthError { max_depth });
219 }
220 }
221 b'}' | b']' => depth = depth.saturating_sub(1),
222 _ => {}
223 }
224 }
225 Ok(())
226}
227
228#[derive(Debug)]
229struct JsonSyntaxDepthError {
230 max_depth: usize,
231}
232
233impl std::fmt::Display for JsonSyntaxDepthError {
234 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 write!(
236 formatter,
237 "JSON nesting exceeds the {}-container limit",
238 self.max_depth
239 )
240 }
241}
242
243impl std::error::Error for JsonSyntaxDepthError {}
244
245fn validate_component(
246 component: &JsonComponent,
247) -> Result<(), crate::component::ComponentDepthError> {
248 component.validate_depth(JsonTextComponent::MAX_COMPONENT_DEPTH)?;
249 component.validate_dynamic_depth(JsonTextComponent::MAX_COMPONENT_DEPTH)
250}
251
252fn json_validation_error(
253 source: impl std::error::Error + Send + Sync + 'static,
254) -> serde_json::Error {
255 serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::InvalidData, source))
256}