Skip to main content

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}