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::{RefReader, RefWriter};
28use crate::resolver::{TypeInfo, TypeResolver};
29use crate::serializer::StructSerializer;
30use crate::type_id as types;
31use crate::TypeId;
32use std::rc::Rc;
33
34pub struct ContextCache<T> {
38 cached_id: u64,
40 cached_context: Option<Box<T>>,
41 others: HashMap<u64, Box<T>>,
43}
44
45impl<T> ContextCache<T> {
46 pub fn new() -> Self {
47 ContextCache {
48 cached_id: u64::MAX,
49 cached_context: None,
50 others: HashMap::new(),
51 }
52 }
53
54 #[inline(always)]
55 pub fn get_or_insert(&mut self, id: u64, create: impl FnOnce() -> Box<T>) -> &mut T {
56 if self.cached_id == id {
57 return self.cached_context.as_mut().unwrap();
59 }
60
61 if self.cached_context.is_some() {
63 let old_id = self.cached_id;
65 let old_context = self.cached_context.take().unwrap();
66 self.others.insert(old_id, old_context);
67 }
68
69 let context = self.others.remove(&id).unwrap_or_else(create);
71 self.cached_id = id;
72 self.cached_context = Some(context);
73 self.cached_context.as_mut().unwrap()
74 }
75
76 #[inline(always)]
79 pub fn get_or_insert_result<E>(
80 &mut self,
81 id: u64,
82 create: impl FnOnce() -> Result<Box<T>, E>,
83 ) -> Result<&mut T, E> {
84 if self.cached_id == id {
85 return Ok(self.cached_context.as_mut().unwrap());
87 }
88
89 if self.cached_context.is_some() {
91 let old_id = self.cached_id;
93 let old_context = self.cached_context.take().unwrap();
94 self.others.insert(old_id, old_context);
95 }
96
97 let context = match self.others.remove(&id) {
99 Some(ctx) => ctx,
100 None => create()?,
101 };
102 self.cached_id = id;
103 self.cached_context = Some(context);
104 Ok(self.cached_context.as_mut().unwrap())
105 }
106}
107
108impl<T> Default for ContextCache<T> {
109 fn default() -> Self {
110 Self::new()
111 }
112}
113
114#[allow(clippy::needless_lifetimes)]
117pub struct WriteContext<'a> {
118 type_resolver: TypeResolver,
120 compatible: bool,
121 share_meta: bool,
122 compress_string: bool,
123 xlang: bool,
124 check_struct_version: bool,
125 track_ref: bool,
126
127 default_writer: Option<Writer<'a>>,
129 pub writer: Writer<'a>,
130 meta_resolver: MetaWriterResolver,
131 meta_string_resolver: MetaStringWriterResolver,
132 pub ref_writer: RefWriter,
133}
134
135#[allow(clippy::needless_lifetimes)]
136impl<'a> WriteContext<'a> {
137 pub fn new(type_resolver: TypeResolver, config: Config) -> WriteContext<'a> {
138 WriteContext {
139 type_resolver,
140 compatible: config.compatible,
141 share_meta: config.share_meta,
142 compress_string: config.compress_string,
143 xlang: config.xlang,
144 check_struct_version: config.check_struct_version,
145 track_ref: config.track_ref,
146 default_writer: None,
147 writer: Writer::from_buffer(Self::get_leak_buffer()),
148 meta_resolver: MetaWriterResolver::default(),
149 meta_string_resolver: MetaStringWriterResolver::default(),
150 ref_writer: RefWriter::new(),
151 }
152 }
153
154 #[inline(always)]
155 fn get_leak_buffer() -> &'static mut Vec<u8> {
156 Box::leak(Box::new(vec![]))
157 }
158
159 #[inline(always)]
160 pub fn attach_writer(&mut self, writer: Writer<'a>) {
161 let old = mem::replace(&mut self.writer, writer);
162 self.default_writer = Some(old);
163 }
164
165 #[inline(always)]
166 pub fn detach_writer(&mut self) {
167 let default = mem::take(&mut self.default_writer);
168 self.writer = default.unwrap();
169 }
170
171 #[inline(always)]
173 pub fn get_type_resolver(&self) -> &TypeResolver {
174 &self.type_resolver
175 }
176
177 #[inline(always)]
178 pub fn get_provider_type_info(
179 &self,
180 provider_type_id: &std::any::TypeId,
181 ) -> Result<Rc<TypeInfo>, Error> {
182 self.type_resolver.get_provider_type_info(provider_type_id)
183 }
184
185 #[inline(always)]
186 pub fn get_target_type_info(
187 &self,
188 target_type_id: &std::any::TypeId,
189 ) -> Result<Rc<TypeInfo>, Error> {
190 self.type_resolver.get_target_type_info(target_type_id)
191 }
192
193 #[inline(always)]
195 pub fn is_compatible(&self) -> bool {
196 self.compatible
197 }
198
199 #[inline(always)]
201 pub fn is_share_meta(&self) -> bool {
202 self.share_meta
203 }
204
205 #[inline(always)]
207 pub fn is_compress_string(&self) -> bool {
208 self.compress_string
209 }
210
211 #[inline(always)]
213 pub fn is_xlang(&self) -> bool {
214 self.xlang
215 }
216
217 #[inline(always)]
219 pub fn is_check_struct_version(&self) -> bool {
220 self.check_struct_version
221 }
222
223 #[inline(always)]
225 pub fn is_track_ref(&self) -> bool {
226 self.track_ref
227 }
228
229 #[inline(always)]
232 pub fn write_type_meta(&mut self, type_id: std::any::TypeId) -> Result<(), Error> {
233 self.meta_resolver
234 .write_type_meta(&mut self.writer, type_id, &self.type_resolver)
235 }
236
237 #[inline(always)]
239 pub fn write_struct_type_info<T: StructSerializer>(&mut self) -> Result<(), Error> {
240 let rust_type_id = std::any::TypeId::of::<T>();
241 let type_index = T::type_index();
242 let type_id = self.type_resolver.get_type_id_by_index(type_index)?;
243 match type_id {
244 TypeId::STRUCT | TypeId::ENUM | TypeId::EXT | TypeId::TYPED_UNION => {
245 self.writer.write_u8(type_id as u8);
246 let user_type_id = self
247 .type_resolver
248 .get_user_type_id_by_index(&rust_type_id, type_index)?;
249 self.writer.write_var_u32(user_type_id);
250 }
251 TypeId::COMPATIBLE_STRUCT | TypeId::NAMED_COMPATIBLE_STRUCT => {
252 self.writer.write_u8(type_id as u8);
253 self.meta_resolver.write_type_meta_fast(
254 &mut self.writer,
255 rust_type_id,
256 type_index,
257 &self.type_resolver,
258 )?;
259 }
260 TypeId::NAMED_ENUM | TypeId::NAMED_EXT | TypeId::NAMED_STRUCT | TypeId::NAMED_UNION
261 if self.is_share_meta() =>
262 {
263 self.writer.write_u8(type_id as u8);
264 self.meta_resolver.write_type_meta_fast(
265 &mut self.writer,
266 rust_type_id,
267 type_index,
268 &self.type_resolver,
269 )?;
270 }
271 _ => {
272 self.write_provider_type_info(type_id as u32, rust_type_id)?;
273 }
274 }
275 Ok(())
276 }
277
278 pub fn write_provider_type_info(
279 &mut self,
280 wire_type_id: u32,
281 provider_type_id: std::any::TypeId,
282 ) -> Result<Rc<TypeInfo>, Error> {
283 let type_info = self
284 .type_resolver
285 .get_provider_type_info(&provider_type_id)?;
286 self.write_resolved_type_info(wire_type_id, type_info)
287 }
288
289 pub fn write_target_type_info(
290 &mut self,
291 wire_type_id: u32,
292 target_type_id: std::any::TypeId,
293 ) -> Result<Rc<TypeInfo>, Error> {
294 let type_info = self.type_resolver.get_target_type_info(&target_type_id)?;
295 self.write_resolved_type_info(wire_type_id, type_info)
296 }
297
298 #[doc(hidden)]
299 #[inline(always)]
300 pub fn write_resolved_type_info(
301 &mut self,
302 wire_type_id: u32,
303 type_info: Rc<TypeInfo>,
304 ) -> Result<Rc<TypeInfo>, Error> {
305 if types::is_internal_type(wire_type_id) {
306 self.writer.write_u8(wire_type_id as u8);
307 return Ok(type_info);
308 }
309 let wire_type_id = type_info.get_type_id();
310 let namespace = type_info.get_namespace();
311 let type_name = type_info.get_type_name();
312 self.writer.write_u8(wire_type_id as u8);
313 match wire_type_id {
315 TypeId::ENUM | TypeId::STRUCT | TypeId::EXT | TypeId::TYPED_UNION => {
316 let user_type_id = type_info.get_user_type_id();
317 self.writer.write_var_u32(user_type_id);
318 }
319 TypeId::COMPATIBLE_STRUCT | TypeId::NAMED_COMPATIBLE_STRUCT => {
320 self.meta_resolver
321 .write_resolved_type_meta(&mut self.writer, &type_info)?;
322 }
323 TypeId::NAMED_ENUM | TypeId::NAMED_EXT | TypeId::NAMED_STRUCT | TypeId::NAMED_UNION => {
324 if self.is_share_meta() {
325 self.meta_resolver
326 .write_resolved_type_meta(&mut self.writer, &type_info)?;
327 } else {
328 self.write_meta_string_bytes(namespace)?;
329 self.write_meta_string_bytes(type_name)?;
330 }
331 }
332 _ => {
333 }
335 }
336 Ok(type_info)
337 }
338
339 #[inline(always)]
340 pub fn write_meta_string_bytes(&mut self, ms: Rc<MetaString>) -> Result<(), Error> {
341 self.meta_string_resolver
342 .write_meta_string_bytes(&mut self.writer, ms)
343 }
344
345 #[inline(always)]
346 pub fn reset(&mut self) {
347 self.meta_resolver.reset();
348 self.meta_string_resolver.reset();
349 self.ref_writer.reset();
350 }
351}
352
353#[allow(clippy::needless_lifetimes)]
354impl<'a> Drop for WriteContext<'a> {
355 fn drop(&mut self) {
356 unsafe {
357 drop(Box::from_raw(self.writer.bf));
358 }
359 }
360}
361
362pub struct ReadContext<'a> {
365 type_resolver: TypeResolver,
367 config: Config,
368 compatible: bool,
369 share_meta: bool,
370 xlang: bool,
371 max_dyn_depth: u32,
372 check_struct_version: bool,
373 check_string_read: bool,
374 pub(crate) remaining_graph_memory_bytes: usize,
375 pub(crate) remaining_unbacked_container_items: usize,
376
377 pub reader: Reader<'a>,
379 pub meta_resolver: MetaReaderResolver,
380 meta_string_resolver: MetaStringReaderResolver,
381 pub ref_reader: RefReader,
382 current_depth: u32,
383}
384
385impl<'a> ReadContext<'a> {
386 pub fn new(type_resolver: TypeResolver, config: Config) -> ReadContext<'a> {
387 ReadContext {
388 type_resolver,
389 config: config.clone(),
390 compatible: config.compatible,
391 share_meta: config.share_meta,
392 xlang: config.xlang,
393 max_dyn_depth: config.max_dyn_depth,
394 check_struct_version: config.check_struct_version,
395 check_string_read: config.check_string_read,
396 remaining_graph_memory_bytes: 0,
397 remaining_unbacked_container_items: 0,
398 reader: Reader::default(),
399 meta_resolver: MetaReaderResolver::default(),
400 meta_string_resolver: MetaStringReaderResolver::default(),
401 ref_reader: RefReader::new(),
402 current_depth: 0,
403 }
404 }
405
406 #[inline(always)]
408 pub fn get_type_resolver(&self) -> &TypeResolver {
409 &self.type_resolver
410 }
411
412 #[inline(always)]
414 pub fn is_compatible(&self) -> bool {
415 self.compatible
416 }
417
418 #[inline(always)]
420 pub fn is_share_meta(&self) -> bool {
421 self.share_meta
422 }
423
424 #[inline(always)]
426 pub fn is_xlang(&self) -> bool {
427 self.xlang
428 }
429
430 #[inline(always)]
432 pub fn is_check_struct_version(&self) -> bool {
433 self.check_struct_version
434 }
435
436 #[inline(always)]
438 pub fn is_check_string_read(&self) -> bool {
439 self.check_string_read
440 }
441
442 #[inline(always)]
444 pub fn max_dyn_depth(&self) -> u32 {
445 self.max_dyn_depth
446 }
447
448 #[inline(always)]
449 pub fn attach_reader(&mut self, reader: Reader<'a>) {
450 self.reader = reader;
451 }
452
453 #[inline(always)]
454 #[doc(hidden)]
455 pub fn reserve_graph_memory(&mut self, bytes: usize) -> Result<(), Error> {
456 let remaining = self.remaining_graph_memory_bytes;
457 if bytes > remaining {
458 return Err(graph_memory_exceeded(
459 bytes,
460 remaining,
461 self.config.max_graph_memory_bytes,
462 ));
463 }
464 self.remaining_graph_memory_bytes = remaining - bytes;
465 Ok(())
466 }
467
468 #[inline(always)]
469 #[doc(hidden)]
470 pub fn remaining_unbacked_container_items(&self) -> usize {
471 self.remaining_unbacked_container_items
472 }
473
474 #[inline(always)]
475 #[doc(hidden)]
476 pub fn reserve_unbacked_container_items(&mut self, items: usize) -> Result<(), Error> {
477 let remaining = self.remaining_unbacked_container_items;
478 if items > remaining {
479 return Err(unbacked_container_items_exceeded(items, remaining));
480 }
481 self.remaining_unbacked_container_items = remaining - items;
482 Ok(())
483 }
484
485 #[inline(always)]
486 pub fn detach_reader(&mut self) -> Reader<'_> {
487 mem::take(&mut self.reader)
488 }
489
490 #[inline(always)]
491 pub fn get_type_info_by_index(&self, type_index: usize) -> Result<&Rc<TypeInfo>, Error> {
492 self.meta_resolver.get(type_index).ok_or_else(|| {
493 Error::type_error(format!("TypeInfo not found for type index: {}", type_index))
494 })
495 }
496
497 #[inline(always)]
498 pub fn get_meta(&self, type_index: usize) -> Result<&Rc<TypeInfo>, Error> {
499 self.get_type_info_by_index(type_index)
500 }
501
502 #[inline(always)]
505 pub fn read_type_meta(&mut self) -> Result<Rc<TypeInfo>, Error> {
506 self.meta_resolver
507 .read_type_meta(&mut self.reader, &self.type_resolver, &self.config)
508 }
509
510 #[inline(always)]
511 fn read_type_meta_for(&mut self, expected: &Rc<TypeInfo>) -> Result<Rc<TypeInfo>, Error> {
512 self.meta_resolver.read_type_meta_for(
513 &mut self.reader,
514 &self.type_resolver,
515 &self.config,
516 expected,
517 )
518 }
519
520 #[inline(always)]
521 fn read_struct_type_meta_for(
522 &mut self,
523 expected: &Rc<TypeInfo>,
524 ) -> Result<Rc<TypeInfo>, Error> {
525 self.meta_resolver.read_struct_type_meta_for(
526 &mut self.reader,
527 &self.type_resolver,
528 &self.config,
529 expected,
530 )
531 }
532
533 pub fn read_any_type_info(&mut self) -> Result<Rc<TypeInfo>, Error> {
534 self.read_any_type_info_with_expected(None, false)
535 }
536
537 #[inline(always)]
538 pub(crate) fn read_type_info_for(
539 &mut self,
540 expected_target: std::any::TypeId,
541 ) -> Result<Rc<TypeInfo>, Error> {
542 let expected = self.type_resolver.get_target_type_info(&expected_target)?;
543 self.read_any_type_info_with_expected(Some(&expected), false)
544 }
545
546 #[inline(always)]
547 pub(crate) fn read_struct_type_info_for(
548 &mut self,
549 expected_target: std::any::TypeId,
550 ) -> Result<Rc<TypeInfo>, Error> {
551 let expected = self.type_resolver.get_target_type_info(&expected_target)?;
552 self.read_any_type_info_with_expected(Some(&expected), true)
553 }
554
555 fn read_any_type_info_with_expected(
556 &mut self,
557 expected: Option<&Rc<TypeInfo>>,
558 allow_structural_stub: bool,
559 ) -> Result<Rc<TypeInfo>, Error> {
560 let fory_type_id = self.reader.read_u8()? as u32;
561 let type_info = match fory_type_id {
563 types::ENUM | types::STRUCT | types::EXT | types::TYPED_UNION => {
564 let user_type_id = self.reader.read_var_u32()?;
565 self.type_resolver
566 .get_user_type_info_by_id(user_type_id)
567 .ok_or_else(|| Error::type_error("ID harness not found"))?
568 }
569 types::COMPATIBLE_STRUCT | types::NAMED_COMPATIBLE_STRUCT => {
570 return match expected {
572 Some(expected) if allow_structural_stub => {
573 self.read_struct_type_meta_for(expected)
574 }
575 Some(expected) => self.read_type_meta_for(expected),
576 None => self.read_type_meta(),
577 };
578 }
579 types::NAMED_ENUM | types::NAMED_EXT | types::NAMED_STRUCT | types::NAMED_UNION => {
580 if self.is_share_meta() {
581 return match expected {
583 Some(expected) if allow_structural_stub => {
584 self.read_struct_type_meta_for(expected)
585 }
586 Some(expected) => self.read_type_meta_for(expected),
587 None => self.read_type_meta(),
588 };
589 } else {
590 self.read_named_type_info()?
591 }
592 }
593 _ => self
594 .type_resolver
595 .get_type_info_by_id(fory_type_id)
596 .ok_or_else(|| Error::type_error("ID harness not found"))?,
597 };
598 if let Some(expected) = expected {
599 let expected_target = expected
600 .get_harness()
601 .target_type_id()
602 .ok_or_else(|| Error::type_error("expected TypeInfo has no concrete target"))?;
603 let resolved_target = type_info.get_harness().target_type_id();
604 if resolved_target != Some(expected_target)
605 && !(allow_structural_stub && resolved_target.is_none())
606 {
607 return Err(Error::type_error(
608 "resolved TypeInfo target does not match declared target",
609 ));
610 }
611 }
612 Ok(type_info)
613 }
614
615 #[inline(never)]
618 fn read_named_type_info(&mut self) -> Result<Rc<TypeInfo>, Error> {
619 let namespace = self.read_meta_string()?.to_owned();
620 let type_name = self.read_meta_string()?.to_owned();
621 let rc_namespace = Rc::from(namespace.clone());
622 let rc_type_name = Rc::from(type_name.clone());
623 self.type_resolver
624 .get_type_info_by_meta_string_name(rc_namespace, rc_type_name)
625 .or_else(|| {
626 self.type_resolver
627 .get_type_info_by_name(namespace.original.as_str(), type_name.original.as_str())
628 })
629 .ok_or_else(|| {
630 Error::type_error(format!(
631 "Name harness not found: namespace='{}', type='{}'",
632 namespace.original, type_name.original
633 ))
634 })
635 }
636
637 #[inline(always)]
638 pub fn get_provider_type_info(
639 &self,
640 provider_type_id: &std::any::TypeId,
641 ) -> Result<Rc<TypeInfo>, Error> {
642 self.type_resolver.get_provider_type_info(provider_type_id)
643 }
644
645 #[inline(always)]
646 pub fn get_target_type_info(
647 &self,
648 target_type_id: &std::any::TypeId,
649 ) -> Result<Rc<TypeInfo>, Error> {
650 self.type_resolver.get_target_type_info(target_type_id)
651 }
652
653 #[inline(always)]
654 pub fn read_meta_string(&mut self) -> Result<&MetaString, Error> {
655 self.meta_string_resolver.read_meta_string(&mut self.reader)
656 }
657
658 #[inline(always)]
659 pub fn inc_depth(&mut self) -> Result<(), Error> {
660 self.current_depth += 1;
661 if self.current_depth > self.max_dyn_depth() {
662 return Err(Error::depth_exceed(format!(
663 "Maximum dynamic object nesting depth ({}) exceeded. Current depth: {}. \
664 This may indicate a circular reference or overly deep object graph. \
665 Consider increasing max_dyn_depth if this is expected.",
666 self.max_dyn_depth(),
667 self.current_depth
668 )));
669 }
670 Ok(())
671 }
672
673 #[inline(always)]
674 pub fn dec_depth(&mut self) {
675 self.current_depth = self.current_depth.saturating_sub(1);
678 }
679
680 #[inline(always)]
681 pub fn reset(&mut self) {
682 self.meta_resolver.reset();
683 self.meta_string_resolver.reset();
684 self.ref_reader.reset();
685 self.current_depth = 0;
687 self.remaining_unbacked_container_items = 0;
688 }
689}
690
691#[cold]
692#[inline(never)]
693fn graph_memory_exceeded(bytes: usize, remaining: usize, limit: usize) -> Error {
694 Error::invalid_data(format!(
695 "estimated graph memory request {} bytes exceeds max_graph_memory_bytes remaining budget {} bytes out of effective limit {} bytes",
696 bytes, remaining, limit
697 ))
698}
699
700#[cold]
701#[inline(never)]
702fn unbacked_container_items_exceeded(items: usize, remaining: usize) -> Error {
703 Error::invalid_data(format!(
704 "container read work request {items} items exceeds max_unbacked_container_items remaining budget {remaining} items"
705 ))
706}