mcproto_types/
json_text_component.rs1use std::io::{Read, Write};
7
8use mcproto_codec::error::{CodecError, CodecKind, CodecOperation, InvalidEncodingReason};
9use serde::{Deserialize, Serialize};
10
11use crate::{
12 TypeCodec,
13 basic::{decode_prefixed_string, encode_prefixed_string},
14 component::JsonComponent,
15};
16
17pub use serde_json::Value as JsonValue;
19
20#[derive(Debug, Clone, PartialEq)]
28pub struct JsonTextComponent(
29 pub JsonComponent,
31);
32
33impl JsonTextComponent {
34 pub const MAX_DECODE_UTF16_CODE_UNITS: usize = 262_144;
36 pub const MAX_DECODE_BYTES: usize = Self::MAX_DECODE_UTF16_CODE_UNITS * 3;
38 pub const MAX_DECODE_ENCODED_BYTES: usize = Self::MAX_DECODE_BYTES + 3;
40
41 pub const MAX_ENCODE_UTF16_CODE_UNITS: usize = 32_767;
46 pub const MAX_ENCODE_BYTES: usize = Self::MAX_ENCODE_UTF16_CODE_UNITS * 3;
48 pub const MAX_ENCODE_ENCODED_BYTES: usize = Self::MAX_ENCODE_BYTES + 3;
50
51 const MAX_COMPONENT_DEPTH: usize = 512;
52
53 pub fn text(value: impl Into<String>) -> Self {
55 Self(JsonComponent::text(value))
56 }
57
58 pub fn from_json_str(value: &str) -> Result<Self, CodecError> {
68 let component = deserialize_json(value)
69 .map_err(|source| Self::invalid_json(CodecOperation::Read, value.len(), source))?;
70 validate_component(&component)
71 .map_err(|source| Self::invalid_json(CodecOperation::Read, value.len(), source))?;
72 Ok(Self(component))
73 }
74
75 fn invalid_json(
76 operation: CodecOperation,
77 bytes_processed: usize,
78 source: impl std::error::Error + Send + Sync + 'static,
79 ) -> CodecError {
80 CodecError::invalid_encoding_for_operation_with_source(
81 CodecKind::JsonTextComponent,
82 operation,
83 bytes_processed,
84 InvalidEncodingReason::InvalidJson,
85 source,
86 )
87 }
88}
89
90impl Default for JsonTextComponent {
91 fn default() -> Self {
92 Self::text("")
93 }
94}
95
96impl From<JsonComponent> for JsonTextComponent {
97 fn from(value: JsonComponent) -> Self {
98 Self(value)
99 }
100}
101
102impl From<String> for JsonTextComponent {
103 fn from(value: String) -> Self {
104 Self::text(value)
105 }
106}
107
108impl From<&str> for JsonTextComponent {
109 fn from(value: &str) -> Self {
110 Self::text(value)
111 }
112}
113
114impl TypeCodec for JsonTextComponent {
115 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
116 validate_component(&self.0)
117 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
118 let mut bytes = Vec::new();
119 let mut serializer = serde_json::Serializer::new(&mut bytes);
120 self.0
121 .serialize(serde_stacker::Serializer::new(&mut serializer))
122 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
123 let json = String::from_utf8(bytes)
124 .map_err(|source| Self::invalid_json(CodecOperation::Write, 0, source))?;
125 encode_prefixed_string(
126 &json,
127 writer,
128 CodecKind::JsonTextComponent,
129 Self::MAX_ENCODE_BYTES,
130 Self::MAX_ENCODE_UTF16_CODE_UNITS,
131 )
132 }
133
134 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
135 let (json, bytes_processed) = decode_prefixed_string(
136 reader,
137 CodecKind::JsonTextComponent,
138 Self::MAX_DECODE_BYTES,
139 Self::MAX_DECODE_UTF16_CODE_UNITS,
140 )?;
141 let component = deserialize_json(&json)
142 .map_err(|source| Self::invalid_json(CodecOperation::Read, bytes_processed, source))?;
143 validate_component(&component)
144 .map_err(|source| Self::invalid_json(CodecOperation::Read, bytes_processed, source))?;
145 Ok(Self(component))
146 }
147}
148
149fn deserialize_json(value: &str) -> Result<JsonComponent, serde_json::Error> {
150 validate_json_syntax_depth(value, JsonTextComponent::MAX_COMPONENT_DEPTH * 2 + 8)
151 .map_err(json_validation_error)?;
152 let mut deserializer = serde_json::Deserializer::from_str(value);
153 deserializer.disable_recursion_limit();
154 let component =
155 JsonComponent::deserialize(serde_stacker::Deserializer::new(&mut deserializer))?;
156 deserializer.end()?;
157 Ok(component)
158}
159
160fn validate_json_syntax_depth(value: &str, max_depth: usize) -> Result<(), JsonSyntaxDepthError> {
161 let mut depth = 0_usize;
162 let mut in_string = false;
163 let mut escaped = false;
164 for byte in value.bytes() {
165 if in_string {
166 if escaped {
167 escaped = false;
168 } else if byte == b'\\' {
169 escaped = true;
170 } else if byte == b'"' {
171 in_string = false;
172 }
173 continue;
174 }
175 match byte {
176 b'"' => in_string = true,
177 b'{' | b'[' => {
178 depth += 1;
179 if depth > max_depth {
180 return Err(JsonSyntaxDepthError { max_depth });
181 }
182 }
183 b'}' | b']' => depth = depth.saturating_sub(1),
184 _ => {}
185 }
186 }
187 Ok(())
188}
189
190#[derive(Debug)]
191struct JsonSyntaxDepthError {
192 max_depth: usize,
193}
194
195impl std::fmt::Display for JsonSyntaxDepthError {
196 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(
198 formatter,
199 "JSON nesting exceeds the {}-container limit",
200 self.max_depth
201 )
202 }
203}
204
205impl std::error::Error for JsonSyntaxDepthError {}
206
207fn validate_component(
208 component: &JsonComponent,
209) -> Result<(), crate::component::ComponentDepthError> {
210 component.validate_depth(JsonTextComponent::MAX_COMPONENT_DEPTH)?;
211 component.validate_dynamic_depth(JsonTextComponent::MAX_COMPONENT_DEPTH)
212}
213
214fn json_validation_error(
215 source: impl std::error::Error + Send + Sync + 'static,
216) -> serde_json::Error {
217 serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::InvalidData, source))
218}