fory_core/resolver/ref_resolver.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::buffer::{Reader, Writer};
19use crate::error::Error;
20use crate::types::RefFlag;
21use std::any::Any;
22use std::collections::HashMap;
23use std::rc::Rc;
24use std::sync::Arc;
25
26/// Reference writer for tracking shared references during serialization.
27///
28/// RefWriter maintains a mapping from object pointer addresses to reference IDs,
29/// allowing the serialization system to detect when the same object is encountered
30/// multiple times and write a reference instead of serializing the object again.
31/// This enables proper handling of shared references and circular references.
32///
33/// # Examples
34///
35/// ```rust
36/// use fory_core::buffer::Writer;
37/// use fory_core::resolver::ref_resolver::RefWriter;
38/// use std::rc::Rc;
39///
40/// let mut ref_writer = RefWriter::new();
41/// let mut buffer = vec![];
42/// let mut writer = Writer::from_buffer(&mut buffer);
43/// let rc = Rc::new(42);
44///
45/// // First encounter - returns false, indicating object should be serialized
46/// assert!(!ref_writer.try_write_rc_ref(&mut writer, &rc));
47///
48/// // Second encounter - returns true, indicating reference was written
49/// let rc2 = rc.clone();
50/// assert!(ref_writer.try_write_rc_ref(&mut writer, &rc2));
51/// ```
52#[derive(Default)]
53pub struct RefWriter {
54 /// Maps pointer addresses to reference IDs
55 refs: HashMap<usize, u32>,
56 /// Next reference ID to assign
57 next_ref_id: u32,
58}
59
60type UpdateCallback = Box<dyn FnOnce(&RefReader)>;
61
62impl RefWriter {
63 /// Creates a new RefWriter instance.
64 pub fn new() -> Self {
65 Self::default()
66 }
67
68 /// Attempt to write a reference for an `Rc<T>`.
69 ///
70 /// Returns true if a reference was written (indicating this object has been
71 /// seen before), false if this is the first occurrence and the object should
72 /// be serialized normally.
73 ///
74 /// # Arguments
75 ///
76 /// * `writer` - The writer to write reference information to
77 /// * `rc` - The Rc to check for reference tracking
78 ///
79 /// # Returns
80 ///
81 /// * `true` if a reference was written
82 /// * `false` if this is the first occurrence of the object
83 #[inline]
84 pub fn try_write_rc_ref<T: ?Sized>(&mut self, writer: &mut Writer, rc: &Rc<T>) -> bool {
85 let ptr_addr = Rc::as_ptr(rc) as *const () as usize;
86
87 if let Some(&ref_id) = self.refs.get(&ptr_addr) {
88 writer.write_i8(RefFlag::Ref as i8);
89 writer.write_var_uint32(ref_id);
90 true
91 } else {
92 let ref_id = self.next_ref_id;
93 self.next_ref_id += 1;
94 self.refs.insert(ptr_addr, ref_id);
95 writer.write_i8(RefFlag::RefValue as i8);
96 false
97 }
98 }
99
100 /// Attempt to write a reference for an `Arc<T>`.
101 ///
102 /// Returns true if a reference was written (indicating this object has been
103 /// seen before), false if this is the first occurrence and the object should
104 /// be serialized normally.
105 ///
106 /// # Arguments
107 ///
108 /// * `writer` - The writer to write reference information to
109 /// * `arc` - The Arc to check for reference tracking
110 ///
111 /// # Returns
112 ///
113 /// * `true` if a reference was written
114 /// * `false` if this is the first occurrence of the object
115 #[inline]
116 pub fn try_write_arc_ref<T: ?Sized>(&mut self, writer: &mut Writer, arc: &Arc<T>) -> bool {
117 let ptr_addr = Arc::as_ptr(arc) as *const () as usize;
118
119 if let Some(&ref_id) = self.refs.get(&ptr_addr) {
120 // This object has been seen before, write a reference
121 writer.write_i8(RefFlag::Ref as i8);
122 writer.write_var_uint32(ref_id);
123 true
124 } else {
125 // First time seeing this object, register it and return false
126 let ref_id = self.next_ref_id;
127 self.next_ref_id += 1;
128 self.refs.insert(ptr_addr, ref_id);
129 writer.write_i8(RefFlag::RefValue as i8);
130 false
131 }
132 }
133
134 /// Reserve a reference ID slot without storing anything.
135 ///
136 /// This is used for xlang compatibility where ALL objects (including struct values,
137 /// not just Rc/Arc) participate in reference tracking.
138 ///
139 /// # Returns
140 ///
141 /// The reserved reference ID
142 #[inline(always)]
143 pub fn reserve_ref_id(&mut self) -> u32 {
144 let ref_id = self.next_ref_id;
145 self.next_ref_id += 1;
146 ref_id
147 }
148
149 /// Clear all stored references.
150 ///
151 /// This is useful for reusing the RefWriter for multiple serialization operations.
152 #[inline(always)]
153 pub fn reset(&mut self) {
154 self.refs.clear();
155 self.next_ref_id = 0;
156 }
157}
158
159/// Reference reader for resolving shared references during deserialization.
160///
161/// RefReader maintains a vector of previously deserialized objects that can be
162/// referenced by ID. When a reference is encountered during deserialization,
163/// the RefReader can return the previously deserialized object instead of
164/// deserializing it again.
165///
166/// # Examples
167///
168/// ```rust
169/// use fory_core::resolver::ref_resolver::RefReader;
170/// use std::rc::Rc;
171///
172/// let mut ref_reader = RefReader::new();
173/// let rc = Rc::new(42);
174///
175/// // Store an object for later reference
176/// let ref_id = ref_reader.store_rc_ref(rc.clone());
177///
178/// // Retrieve the object by reference ID
179/// let retrieved = ref_reader.get_rc_ref::<i32>(ref_id).unwrap();
180/// assert!(Rc::ptr_eq(&rc, &retrieved));
181/// ```
182#[derive(Default)]
183pub struct RefReader {
184 /// Vector to store boxed objects for reference resolution
185 refs: Vec<Box<dyn Any>>,
186 /// Callbacks to execute when references are resolved
187 callbacks: Vec<UpdateCallback>,
188}
189
190// danger but useful for multi-thread
191unsafe impl Send for RefReader {}
192unsafe impl Sync for RefReader {}
193
194impl RefReader {
195 /// Creates a new RefReader instance.
196 pub fn new() -> Self {
197 Self::default()
198 }
199
200 /// Reserve a reference ID slot without storing anything yet.
201 ///
202 /// Returns the reserved reference ID that will be used when storing the object later.
203 #[inline(always)]
204 pub fn reserve_ref_id(&mut self) -> u32 {
205 let ref_id = self.refs.len() as u32;
206 self.refs.push(Box::new(()));
207 ref_id
208 }
209
210 /// Store an `Rc<T>` at a previously reserved reference ID.
211 ///
212 /// # Arguments
213 ///
214 /// * `ref_id` - The reference ID that was reserved
215 /// * `rc` - The Rc to store
216 #[inline(always)]
217 pub fn store_rc_ref_at<T: 'static + ?Sized>(&mut self, ref_id: u32, rc: Rc<T>) {
218 self.refs[ref_id as usize] = Box::new(rc);
219 }
220
221 /// Store an `Rc<T>` for later reference resolution during deserialization.
222 ///
223 /// # Arguments
224 ///
225 /// * `rc` - The Rc to store for later reference
226 ///
227 /// # Returns
228 ///
229 /// The reference ID that can be used to retrieve this object later
230 #[inline(always)]
231 pub fn store_rc_ref<T: 'static + ?Sized>(&mut self, rc: Rc<T>) -> u32 {
232 let ref_id = self.refs.len() as u32;
233 self.refs.push(Box::new(rc));
234 ref_id
235 }
236
237 /// Store an `Arc<T>` at a previously reserved reference ID.
238 ///
239 /// # Arguments
240 ///
241 /// * `ref_id` - The reference ID that was reserved
242 /// * `arc` - The Arc to store
243 pub fn store_arc_ref_at<T: 'static + ?Sized>(&mut self, ref_id: u32, arc: Arc<T>) {
244 self.refs[ref_id as usize] = Box::new(arc);
245 }
246
247 /// Store an `Arc<T>` for later reference resolution during deserialization.
248 ///
249 /// # Arguments
250 ///
251 /// * `arc` - The Arc to store for later reference
252 ///
253 /// # Returns
254 ///
255 /// The reference ID that can be used to retrieve this object later
256 #[inline(always)]
257 pub fn store_arc_ref<T: 'static + ?Sized>(&mut self, arc: Arc<T>) -> u32 {
258 let ref_id = self.refs.len() as u32;
259 self.refs.push(Box::new(arc));
260 ref_id
261 }
262
263 /// Get an `Rc<T>` by reference ID during deserialization.
264 ///
265 /// # Arguments
266 ///
267 /// * `ref_id` - The reference ID returned by `store_rc_ref`
268 ///
269 /// # Returns
270 ///
271 /// * `Some(Rc<T>)` if the reference ID is valid and the type matches
272 /// * `None` if the reference ID is invalid or the type doesn't match
273 #[inline(always)]
274 pub fn get_rc_ref<T: 'static + ?Sized>(&self, ref_id: u32) -> Option<Rc<T>> {
275 let any_box = self.refs.get(ref_id as usize)?;
276 any_box.downcast_ref::<Rc<T>>().cloned()
277 }
278
279 /// Get an `Arc<T>` by reference ID during deserialization.
280 ///
281 /// # Arguments
282 ///
283 /// * `ref_id` - The reference ID returned by `store_arc_ref`
284 ///
285 /// # Returns
286 ///
287 /// * `Some(Arc<T>)` if the reference ID is valid and the type matches
288 /// * `None` if the reference ID is invalid or the type doesn't match
289 #[inline(always)]
290 pub fn get_arc_ref<T: 'static + ?Sized>(&self, ref_id: u32) -> Option<Arc<T>> {
291 let any_box = self.refs.get(ref_id as usize)?;
292 any_box.downcast_ref::<Arc<T>>().cloned()
293 }
294
295 /// Add a callback to be executed when weak references are resolved.
296 ///
297 /// # Arguments
298 ///
299 /// * `callback` - A closure that takes a reference to the RefReader
300 #[inline(always)]
301 pub fn add_callback(&mut self, callback: UpdateCallback) {
302 self.callbacks.push(callback);
303 }
304
305 /// Read a reference flag and determine what action to take.
306 ///
307 /// # Arguments
308 ///
309 /// * `reader` - The reader to read the reference flag from
310 ///
311 /// # Returns
312 ///
313 /// The RefFlag indicating what type of reference this is
314 ///
315 /// # Errors
316 ///
317 /// Errors if an invalid reference flag value is encountered
318 #[inline(always)]
319 pub fn read_ref_flag(&self, reader: &mut Reader) -> Result<RefFlag, Error> {
320 let flag_value = reader.read_i8()?;
321 Ok(match flag_value {
322 -3 => RefFlag::Null,
323 -2 => RefFlag::Ref,
324 -1 => RefFlag::NotNullValue,
325 0 => RefFlag::RefValue,
326 _ => Err(Error::invalid_ref(format!(
327 "Invalid reference flag: {}",
328 flag_value
329 )))?,
330 })
331 }
332
333 /// Read a reference ID from the reader.
334 ///
335 /// # Arguments
336 ///
337 /// * `reader` - The reader to read the reference ID from
338 ///
339 /// # Returns
340 ///
341 /// The reference ID as a u32
342 #[inline(always)]
343 pub fn read_ref_id(&self, reader: &mut Reader) -> Result<u32, Error> {
344 reader.read_varuint32()
345 }
346
347 /// Execute all pending callbacks to resolve weak pointer references.
348 ///
349 /// This should be called after deserialization completes to update any weak pointers
350 /// that referenced objects which were not yet available during deserialization.
351 #[inline(always)]
352 pub fn resolve_callbacks(&mut self) {
353 let callbacks = std::mem::take(&mut self.callbacks);
354 for callback in callbacks {
355 callback(self);
356 }
357 }
358
359 /// Clear all stored references and callbacks.
360 ///
361 /// This is useful for reusing the RefReader for multiple deserialization operations.
362 #[inline(always)]
363 pub fn reset(&mut self) {
364 self.resolve_callbacks();
365 self.refs.clear();
366 self.callbacks.clear();
367 }
368}