1use crate::buffer::{Reader, Writer};
19use crate::config::Config;
20use std::collections::HashMap;
21use std::mem;
22
23use crate::error::Error;
24use crate::meta::MetaString;
25use crate::resolver::meta_resolver::{MetaReaderResolver, MetaWriterResolver};
26use crate::resolver::meta_string_resolver::{MetaStringReaderResolver, MetaStringWriterResolver};
27use crate::resolver::ref_resolver::{RefReader, RefWriter};
28use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
29use crate::types;
30use crate::TypeId;
31use std::rc::Rc;
32
33pub struct ContextCache<T> {
37 cached_id: u64,
39 cached_context: Option<Box<T>>,
40 others: HashMap<u64, Box<T>>,
42}
43
44impl<T> ContextCache<T> {
45 pub fn new() -> Self {
46 ContextCache {
47 cached_id: u64::MAX,
48 cached_context: None,
49 others: HashMap::new(),
50 }
51 }
52
53 #[inline(always)]
54 pub fn get_or_insert(&mut self, id: u64, create: impl FnOnce() -> Box<T>) -> &mut T {
55 if self.cached_id == id {
56 return self.cached_context.as_mut().unwrap();
58 }
59
60 if self.cached_context.is_some() {
62 let old_id = self.cached_id;
64 let old_context = self.cached_context.take().unwrap();
65 self.others.insert(old_id, old_context);
66 }
67
68 let context = self.others.remove(&id).unwrap_or_else(create);
70 self.cached_id = id;
71 self.cached_context = Some(context);
72 self.cached_context.as_mut().unwrap()
73 }
74
75 #[inline(always)]
78 pub fn get_or_insert_result<E>(
79 &mut self,
80 id: u64,
81 create: impl FnOnce() -> Result<Box<T>, E>,
82 ) -> Result<&mut T, E> {
83 if self.cached_id == id {
84 return Ok(self.cached_context.as_mut().unwrap());
86 }
87
88 if self.cached_context.is_some() {
90 let old_id = self.cached_id;
92 let old_context = self.cached_context.take().unwrap();
93 self.others.insert(old_id, old_context);
94 }
95
96 let context = match self.others.remove(&id) {
98 Some(ctx) => ctx,
99 None => create()?,
100 };
101 self.cached_id = id;
102 self.cached_context = Some(context);
103 Ok(self.cached_context.as_mut().unwrap())
104 }
105}
106
107impl<T> Default for ContextCache<T> {
108 fn default() -> Self {
109 Self::new()
110 }
111}
112
113#[allow(clippy::needless_lifetimes)]
116pub struct WriteContext<'a> {
117 type_resolver: TypeResolver,
119 compatible: bool,
120 share_meta: bool,
121 compress_string: bool,
122 xlang: bool,
123 check_struct_version: bool,
124 track_ref: bool,
125
126 default_writer: Option<Writer<'a>>,
128 pub writer: Writer<'a>,
129 meta_resolver: MetaWriterResolver,
130 meta_string_resolver: MetaStringWriterResolver,
131 pub ref_writer: RefWriter,
132}
133
134#[allow(clippy::needless_lifetimes)]
135impl<'a> WriteContext<'a> {
136 pub fn new(type_resolver: TypeResolver, config: Config) -> WriteContext<'a> {
137 WriteContext {
138 type_resolver,
139 compatible: config.compatible,
140 share_meta: config.share_meta,
141 compress_string: config.compress_string,
142 xlang: config.xlang,
143 check_struct_version: config.check_struct_version,
144 track_ref: config.track_ref,
145 default_writer: None,
146 writer: Writer::from_buffer(Self::get_leak_buffer()),
147 meta_resolver: MetaWriterResolver::default(),
148 meta_string_resolver: MetaStringWriterResolver::default(),
149 ref_writer: RefWriter::new(),
150 }
151 }
152
153 #[inline(always)]
154 fn get_leak_buffer() -> &'static mut Vec<u8> {
155 Box::leak(Box::new(vec![]))
156 }
157
158 #[inline(always)]
159 pub fn attach_writer(&mut self, writer: Writer<'a>) {
160 let old = mem::replace(&mut self.writer, writer);
161 self.default_writer = Some(old);
162 }
163
164 #[inline(always)]
165 pub fn detach_writer(&mut self) {
166 let default = mem::take(&mut self.default_writer);
167 self.writer = default.unwrap();
168 }
169
170 #[inline(always)]
172 pub fn get_type_resolver(&self) -> &TypeResolver {
173 &self.type_resolver
174 }
175
176 #[inline(always)]
177 pub fn get_type_info(&self, type_id: &std::any::TypeId) -> Result<Rc<TypeInfo>, Error> {
178 self.type_resolver.get_type_info(type_id)
179 }
180
181 #[inline(always)]
183 pub fn is_compatible(&self) -> bool {
184 self.compatible
185 }
186
187 #[inline(always)]
189 pub fn is_share_meta(&self) -> bool {
190 self.share_meta
191 }
192
193 #[inline(always)]
195 pub fn is_compress_string(&self) -> bool {
196 self.compress_string
197 }
198
199 #[inline(always)]
201 pub fn is_xlang(&self) -> bool {
202 self.xlang
203 }
204
205 #[inline(always)]
207 pub fn is_check_struct_version(&self) -> bool {
208 self.check_struct_version
209 }
210
211 #[inline(always)]
213 pub fn is_track_ref(&self) -> bool {
214 self.track_ref
215 }
216
217 #[inline(always)]
220 pub fn write_type_meta(&mut self, type_id: std::any::TypeId) -> Result<(), Error> {
221 self.meta_resolver
222 .write_type_meta(&mut self.writer, type_id, &self.type_resolver)
223 }
224
225 pub fn write_any_type_info(
226 &mut self,
227 fory_type_id: u32,
228 concrete_type_id: std::any::TypeId,
229 ) -> Result<Rc<TypeInfo>, Error> {
230 if types::is_internal_type(fory_type_id) {
231 self.writer.write_u8(fory_type_id as u8);
232 return self
233 .type_resolver
234 .get_type_info_by_id(fory_type_id)
235 .ok_or_else(|| Error::type_error("Type info for internal type not found"));
236 }
237 let type_info = self.type_resolver.get_type_info(&concrete_type_id)?;
238 let fory_type_id = type_info.get_type_id();
239 let namespace = type_info.get_namespace();
240 let type_name = type_info.get_type_name();
241 self.writer.write_u8(fory_type_id as u8);
242 match fory_type_id {
244 TypeId::ENUM | TypeId::STRUCT | TypeId::EXT | TypeId::TYPED_UNION => {
245 let user_type_id = type_info.get_user_type_id();
246 self.writer.write_var_uint32(user_type_id);
247 }
248 TypeId::COMPATIBLE_STRUCT | TypeId::NAMED_COMPATIBLE_STRUCT => {
249 self.meta_resolver.write_type_meta(
251 &mut self.writer,
252 concrete_type_id,
253 &self.type_resolver,
254 )?;
255 }
256 TypeId::NAMED_ENUM | TypeId::NAMED_EXT | TypeId::NAMED_STRUCT | TypeId::NAMED_UNION => {
257 if self.is_share_meta() {
258 self.meta_resolver.write_type_meta(
260 &mut self.writer,
261 concrete_type_id,
262 &self.type_resolver,
263 )?;
264 } else {
265 self.write_meta_string_bytes(namespace)?;
266 self.write_meta_string_bytes(type_name)?;
267 }
268 }
269 _ => {
270 }
272 }
273 Ok(type_info)
274 }
275
276 #[inline(always)]
277 pub fn write_meta_string_bytes(&mut self, ms: Rc<MetaString>) -> Result<(), Error> {
278 self.meta_string_resolver
279 .write_meta_string_bytes(&mut self.writer, ms)
280 }
281
282 #[inline(always)]
283 pub fn reset(&mut self) {
284 self.meta_resolver.reset();
285 self.meta_string_resolver.reset();
286 self.ref_writer.reset();
287 }
288}
289
290#[allow(clippy::needless_lifetimes)]
291impl<'a> Drop for WriteContext<'a> {
292 fn drop(&mut self) {
293 unsafe {
294 drop(Box::from_raw(self.writer.bf));
295 }
296 }
297}
298
299#[allow(clippy::needless_lifetimes)]
304unsafe impl<'a> Send for WriteContext<'a> {}
305#[allow(clippy::needless_lifetimes)]
306unsafe impl<'a> Sync for WriteContext<'a> {}
307
308pub struct ReadContext<'a> {
311 type_resolver: TypeResolver,
313 compatible: bool,
314 share_meta: bool,
315 xlang: bool,
316 max_dyn_depth: u32,
317 check_struct_version: bool,
318
319 pub reader: Reader<'a>,
321 pub meta_resolver: MetaReaderResolver,
322 meta_string_resolver: MetaStringReaderResolver,
323 pub ref_reader: RefReader,
324 current_depth: u32,
325}
326
327#[allow(clippy::needless_lifetimes)]
332unsafe impl<'a> Send for ReadContext<'a> {}
333#[allow(clippy::needless_lifetimes)]
334unsafe impl<'a> Sync for ReadContext<'a> {}
335
336impl<'a> ReadContext<'a> {
337 pub fn new(type_resolver: TypeResolver, config: Config) -> ReadContext<'a> {
338 ReadContext {
339 type_resolver,
340 compatible: config.compatible,
341 share_meta: config.share_meta,
342 xlang: config.xlang,
343 max_dyn_depth: config.max_dyn_depth,
344 check_struct_version: config.check_struct_version,
345 reader: Reader::default(),
346 meta_resolver: MetaReaderResolver::default(),
347 meta_string_resolver: MetaStringReaderResolver::default(),
348 ref_reader: RefReader::new(),
349 current_depth: 0,
350 }
351 }
352
353 #[inline(always)]
355 pub fn get_type_resolver(&self) -> &TypeResolver {
356 &self.type_resolver
357 }
358
359 #[inline(always)]
361 pub fn is_compatible(&self) -> bool {
362 self.compatible
363 }
364
365 #[inline(always)]
367 pub fn is_share_meta(&self) -> bool {
368 self.share_meta
369 }
370
371 #[inline(always)]
373 pub fn is_xlang(&self) -> bool {
374 self.xlang
375 }
376
377 #[inline(always)]
379 pub fn is_check_struct_version(&self) -> bool {
380 self.check_struct_version
381 }
382
383 #[inline(always)]
385 pub fn max_dyn_depth(&self) -> u32 {
386 self.max_dyn_depth
387 }
388
389 #[inline(always)]
390 pub fn attach_reader(&mut self, reader: Reader<'a>) {
391 self.reader = reader;
392 }
393
394 #[inline(always)]
395 pub fn detach_reader(&mut self) -> Reader<'_> {
396 mem::take(&mut self.reader)
397 }
398
399 #[inline(always)]
400 pub fn get_type_info_by_index(&self, type_index: usize) -> Result<&Rc<TypeInfo>, Error> {
401 self.meta_resolver.get(type_index).ok_or_else(|| {
402 Error::type_error(format!("TypeInfo not found for type index: {}", type_index))
403 })
404 }
405
406 #[inline(always)]
407 pub fn get_meta(&self, type_index: usize) -> Result<&Rc<TypeInfo>, Error> {
408 self.get_type_info_by_index(type_index)
409 }
410
411 #[inline(always)]
414 pub fn read_type_meta(&mut self) -> Result<Rc<TypeInfo>, Error> {
415 self.meta_resolver
416 .read_type_meta(&mut self.reader, &self.type_resolver)
417 }
418
419 pub fn read_any_type_info(&mut self) -> Result<Rc<TypeInfo>, Error> {
420 let fory_type_id = self.reader.read_u8()? as u32;
421 match fory_type_id {
423 types::ENUM | types::STRUCT | types::EXT | types::TYPED_UNION => {
424 let user_type_id = self.reader.read_varuint32()?;
425 self.type_resolver
426 .get_user_type_info_by_id(user_type_id)
427 .ok_or_else(|| Error::type_error("ID harness not found"))
428 }
429 types::COMPATIBLE_STRUCT | types::NAMED_COMPATIBLE_STRUCT => {
430 self.read_type_meta()
432 }
433 types::NAMED_ENUM | types::NAMED_EXT | types::NAMED_STRUCT | types::NAMED_UNION => {
434 if self.is_share_meta() {
435 self.read_type_meta()
437 } else {
438 let namespace = self.read_meta_string()?.to_owned();
439 let type_name = self.read_meta_string()?.to_owned();
440 let rc_namespace = Rc::from(namespace.clone());
441 let rc_type_name = Rc::from(type_name.clone());
442 self.type_resolver
443 .get_type_info_by_meta_string_name(rc_namespace, rc_type_name)
444 .or_else(|| {
445 self.type_resolver.get_type_info_by_name(
446 namespace.original.as_str(),
447 type_name.original.as_str(),
448 )
449 })
450 .ok_or_else(|| {
451 Error::type_error(format!(
452 "Name harness not found: namespace='{}', type='{}'",
453 namespace.original, type_name.original
454 ))
455 })
456 }
457 }
458 _ => self
459 .type_resolver
460 .get_type_info_by_id(fory_type_id)
461 .ok_or_else(|| Error::type_error("ID harness not found")),
462 }
463 }
464
465 #[inline(always)]
466 pub fn get_type_info(&self, type_id: &std::any::TypeId) -> Result<Rc<TypeInfo>, Error> {
467 self.type_resolver.get_type_info(type_id)
468 }
469
470 #[inline(always)]
471 pub fn read_meta_string(&mut self) -> Result<&MetaString, Error> {
472 self.meta_string_resolver.read_meta_string(&mut self.reader)
473 }
474
475 #[inline(always)]
476 pub fn inc_depth(&mut self) -> Result<(), Error> {
477 self.current_depth += 1;
478 if self.current_depth > self.max_dyn_depth() {
479 return Err(Error::depth_exceed(format!(
480 "Maximum dynamic object nesting depth ({}) exceeded. Current depth: {}. \
481 This may indicate a circular reference or overly deep object graph. \
482 Consider increasing max_dyn_depth if this is expected.",
483 self.max_dyn_depth(),
484 self.current_depth
485 )));
486 }
487 Ok(())
488 }
489
490 #[inline(always)]
491 pub fn dec_depth(&mut self) {
492 self.current_depth = self.current_depth.saturating_sub(1);
493 }
494
495 #[inline(always)]
496 pub fn reset(&mut self) {
497 self.meta_resolver.reset();
498 self.meta_string_resolver.reset();
499 self.ref_reader.reset();
500 self.current_depth = 0;
501 }
502}