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}