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_varuint32(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_varuint32(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    /// Clear all stored references.
135    ///
136    /// This is useful for reusing the RefWriter for multiple serialization operations.
137    #[inline(always)]
138    pub fn reset(&mut self) {
139        self.refs.clear();
140        self.next_ref_id = 0;
141    }
142}
143
144/// Reference reader for resolving shared references during deserialization.
145///
146/// RefReader maintains a vector of previously deserialized objects that can be
147/// referenced by ID. When a reference is encountered during deserialization,
148/// the RefReader can return the previously deserialized object instead of
149/// deserializing it again.
150///
151/// # Examples
152///
153/// ```rust
154/// use fory_core::resolver::ref_resolver::RefReader;
155/// use std::rc::Rc;
156///
157/// let mut ref_reader = RefReader::new();
158/// let rc = Rc::new(42);
159///
160/// // Store an object for later reference
161/// let ref_id = ref_reader.store_rc_ref(rc.clone());
162///
163/// // Retrieve the object by reference ID
164/// let retrieved = ref_reader.get_rc_ref::<i32>(ref_id).unwrap();
165/// assert!(Rc::ptr_eq(&rc, &retrieved));
166/// ```
167#[derive(Default)]
168pub struct RefReader {
169    /// Vector to store boxed objects for reference resolution
170    refs: Vec<Box<dyn Any>>,
171    /// Callbacks to execute when references are resolved
172    callbacks: Vec<UpdateCallback>,
173}
174
175// danger but useful for multi-thread
176unsafe impl Send for RefReader {}
177unsafe impl Sync for RefReader {}
178
179impl RefReader {
180    /// Creates a new RefReader instance.
181    pub fn new() -> Self {
182        Self::default()
183    }
184
185    /// Reserve a reference ID slot without storing anything yet.
186    ///
187    /// Returns the reserved reference ID that will be used when storing the object later.
188    #[inline(always)]
189    pub fn reserve_ref_id(&mut self) -> u32 {
190        let ref_id = self.refs.len() as u32;
191        self.refs.push(Box::new(()));
192        ref_id
193    }
194
195    /// Store an `Rc<T>` at a previously reserved reference ID.
196    ///
197    /// # Arguments
198    ///
199    /// * `ref_id` - The reference ID that was reserved
200    /// * `rc` - The Rc to store
201    #[inline(always)]
202    pub fn store_rc_ref_at<T: 'static + ?Sized>(&mut self, ref_id: u32, rc: Rc<T>) {
203        self.refs[ref_id as usize] = Box::new(rc);
204    }
205
206    /// Store an `Rc<T>` for later reference resolution during deserialization.
207    ///
208    /// # Arguments
209    ///
210    /// * `rc` - The Rc to store for later reference
211    ///
212    /// # Returns
213    ///
214    /// The reference ID that can be used to retrieve this object later
215    #[inline(always)]
216    pub fn store_rc_ref<T: 'static + ?Sized>(&mut self, rc: Rc<T>) -> u32 {
217        let ref_id = self.refs.len() as u32;
218        self.refs.push(Box::new(rc));
219        ref_id
220    }
221
222    /// Store an `Arc<T>` at a previously reserved reference ID.
223    ///
224    /// # Arguments
225    ///
226    /// * `ref_id` - The reference ID that was reserved
227    /// * `arc` - The Arc to store
228    pub fn store_arc_ref_at<T: 'static + ?Sized>(&mut self, ref_id: u32, arc: Arc<T>) {
229        self.refs[ref_id as usize] = Box::new(arc);
230    }
231
232    /// Store an `Arc<T>` for later reference resolution during deserialization.
233    ///
234    /// # Arguments
235    ///
236    /// * `arc` - The Arc to store for later reference
237    ///
238    /// # Returns
239    ///
240    /// The reference ID that can be used to retrieve this object later
241    #[inline(always)]
242    pub fn store_arc_ref<T: 'static + ?Sized>(&mut self, arc: Arc<T>) -> u32 {
243        let ref_id = self.refs.len() as u32;
244        self.refs.push(Box::new(arc));
245        ref_id
246    }
247
248    /// Get an `Rc<T>` by reference ID during deserialization.
249    ///
250    /// # Arguments
251    ///
252    /// * `ref_id` - The reference ID returned by `store_rc_ref`
253    ///
254    /// # Returns
255    ///
256    /// * `Some(Rc<T>)` if the reference ID is valid and the type matches
257    /// * `None` if the reference ID is invalid or the type doesn't match
258    #[inline(always)]
259    pub fn get_rc_ref<T: 'static + ?Sized>(&self, ref_id: u32) -> Option<Rc<T>> {
260        let any_box = self.refs.get(ref_id as usize)?;
261        any_box.downcast_ref::<Rc<T>>().cloned()
262    }
263
264    /// Get an `Arc<T>` by reference ID during deserialization.
265    ///
266    /// # Arguments
267    ///
268    /// * `ref_id` - The reference ID returned by `store_arc_ref`
269    ///
270    /// # Returns
271    ///
272    /// * `Some(Arc<T>)` if the reference ID is valid and the type matches
273    /// * `None` if the reference ID is invalid or the type doesn't match
274    #[inline(always)]
275    pub fn get_arc_ref<T: 'static + ?Sized>(&self, ref_id: u32) -> Option<Arc<T>> {
276        let any_box = self.refs.get(ref_id as usize)?;
277        any_box.downcast_ref::<Arc<T>>().cloned()
278    }
279
280    /// Add a callback to be executed when weak references are resolved.
281    ///
282    /// # Arguments
283    ///
284    /// * `callback` - A closure that takes a reference to the RefReader
285    #[inline(always)]
286    pub fn add_callback(&mut self, callback: UpdateCallback) {
287        self.callbacks.push(callback);
288    }
289
290    /// Read a reference flag and determine what action to take.
291    ///
292    /// # Arguments
293    ///
294    /// * `reader` - The reader to read the reference flag from
295    ///
296    /// # Returns
297    ///
298    /// The RefFlag indicating what type of reference this is
299    ///
300    /// # Errors
301    ///
302    /// Errors if an invalid reference flag value is encountered
303    #[inline(always)]
304    pub fn read_ref_flag(&self, reader: &mut Reader) -> Result<RefFlag, Error> {
305        let flag_value = reader.read_i8()?;
306        Ok(match flag_value {
307            -3 => RefFlag::Null,
308            -2 => RefFlag::Ref,
309            -1 => RefFlag::NotNullValue,
310            0 => RefFlag::RefValue,
311            _ => Err(Error::invalid_ref(format!(
312                "Invalid reference flag: {}",
313                flag_value
314            )))?,
315        })
316    }
317
318    /// Read a reference ID from the reader.
319    ///
320    /// # Arguments
321    ///
322    /// * `reader` - The reader to read the reference ID from
323    ///
324    /// # Returns
325    ///
326    /// The reference ID as a u32
327    #[inline(always)]
328    pub fn read_ref_id(&self, reader: &mut Reader) -> Result<u32, Error> {
329        reader.read_varuint32()
330    }
331
332    /// Execute all pending callbacks to resolve weak pointer references.
333    ///
334    /// This should be called after deserialization completes to update any weak pointers
335    /// that referenced objects which were not yet available during deserialization.
336    #[inline(always)]
337    pub fn resolve_callbacks(&mut self) {
338        let callbacks = std::mem::take(&mut self.callbacks);
339        for callback in callbacks {
340            callback(self);
341        }
342    }
343
344    /// Clear all stored references and callbacks.
345    ///
346    /// This is useful for reusing the RefReader for multiple deserialization operations.
347    #[inline(always)]
348    pub fn reset(&mut self) {
349        self.resolve_callbacks();
350        self.refs.clear();
351        self.callbacks.clear();
352    }
353}