fory_core/serializer/
weak.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
18//! Weak pointer serialization support for `Rc` and `Arc`.
19//!
20//! This module provides [`RcWeak<T>`] and [`ArcWeak<T>`] wrapper types that integrate
21//! Rust's `std::rc::Weak` / `std::sync::Weak` into the Fory serialization framework,
22//! with full support for:
23//
24//! - **Reference identity tracking** — weak pointers serialize as references to their
25//!   corresponding strong pointers, ensuring shared and circular references in the graph
26//!   are preserved without duplication.
27//! - **Null weak pointers** — if the strong pointer has been dropped or was never set,
28//!   the weak will serialize as a `Null` flag.
29//! - **Forward references during deserialization** — if the strong pointer appears later
30//!   in the serialized data, the weak will be resolved after deserialization using
31//!   `RefReader` callbacks.
32//!
33//! ## When to use
34//!
35//! Use these wrappers when your graph structure contains parent/child relationships
36//! or other shared edges where a strong pointer would cause a reference cycle.
37//! Storing a weak pointer avoids owning the target strongly, but serialization
38//! will preserve the link by reference ID.
39//!
40//! ## Example — Parent/Child Graph
41//!
42//! ```rust,ignore
43//! use fory_core::RcWeak;
44//! use fory_core::Fory;
45//! use std::cell::RefCell;
46//! use std::rc::Rc;
47//! use fory_derive::ForyObject;
48//!
49//! #[derive(ForyObject)]
50//! struct Node {
51//!     value: i32,
52//!     parent: RcWeak<RefCell<Node>>,
53//!     children: Vec<Rc<RefCell<Node>>>,
54//! }
55//!
56//! let mut fory = Fory::default();
57//! fory.register::<Node>(2000);
58//!
59//! let parent = Rc::new(RefCell::new(Node {
60//!     value: 1,
61//!     parent: RcWeak::new(),
62//!     children: vec![],
63//! }));
64//!
65//! let child1 = Rc::new(RefCell::new(Node {
66//!     value: 2,
67//!     parent: RcWeak::from(&parent),
68//!     children: vec![],
69//! }));
70//!
71//! let child2 = Rc::new(RefCell::new(Node {
72//!     value: 3,
73//!     parent: RcWeak::from(&parent),
74//!     children: vec![],
75//! }));
76//!
77//! parent.borrow_mut().children.push(child1);
78//! parent.borrow_mut().children.push(child2);
79//!
80//! let serialized = fory.serialize(&parent);
81//! let deserialized: Rc<RefCell<Node>> = fory.deserialize(&serialized).unwrap();
82//!
83//! assert_eq!(deserialized.borrow().children.len(), 2);
84//! for child in &deserialized.borrow().children {
85//!     let upgraded_parent = child.borrow().parent.upgrade().unwrap();
86//!     assert!(Rc::ptr_eq(&deserialized, &upgraded_parent));
87//! }
88//! ```
89//!
90//! ## Example — Arc for Multi-Threaded Graphs
91//!
92//! ```rust,ignore
93//! use fory_core::ArcWeak;
94//! use fory_core::Fory;
95//! use std::sync::{Arc, Mutex};
96//! use fory_derive::ForyObject;
97//!
98//! #[derive(ForyObject)]
99//! struct Node {
100//!     value: i32,
101//!     parent: ArcWeak<Mutex<Node>>,
102//! }
103//!
104//! let mut fory = Fory::default();
105//! fory.register::<Node>(2001);
106//!
107//! let parent = Arc::new(Mutex::new(Node { value: 1, parent: ArcWeak::new() }));
108//! let child = Arc::new(Mutex::new(Node { value: 2, parent: ArcWeak::from(&parent) }));
109//!
110//! let serialized = fory.serialize(&child);
111//! let deserialized: Arc<Mutex<Node>> = fory.deserialize(&serialized).unwrap();
112//! assert_eq!(deserialized.lock().unwrap().value, 2);
113//! ```
114//!
115//! ## Notes
116//!
117//! - These types share the same `UnsafeCell` across clones, so updating a weak in one clone
118//!   will update all of them.
119//! - During serialization, weak pointers **never serialize the target object's data directly**
120//!   — they only emit a reference to the already-serialized strong pointer, or `Null`.
121//! - During deserialization, unresolved references will be patched up by `RefReader::add_callback`
122//!   once the strong pointer becomes available.
123
124use crate::ensure;
125use crate::error::Error;
126use crate::resolver::context::{ReadContext, WriteContext};
127use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
128use crate::serializer::{ForyDefault, Serializer};
129use crate::types::RefFlag;
130use crate::types::TypeId;
131use std::cell::UnsafeCell;
132use std::rc::Rc;
133use std::sync::Arc;
134
135/// A serializable wrapper around `std::rc::Weak<T>`.
136///
137/// `RcWeak<T>` is designed for use in graph-like structures where nodes may need to hold
138/// non-owning references to other nodes (e.g., parent pointers), and you still want them
139/// to round-trip through serialization while preserving reference identity.
140///
141/// Unlike a raw `Weak<T>`, cloning `RcWeak` keeps all clones pointing to the same
142/// internal `UnsafeCell`, so updates via deserialization callbacks affect all copies.
143///
144/// # Example
145/// See module-level docs for a complete graph example.
146///
147/// # Null handling
148/// If the target `Rc<T>` has been dropped or never assigned, `upgrade()` returns `None`
149/// and serialization will write a `RefFlag::Null` instead of a reference ID.
150pub struct RcWeak<T: ?Sized> {
151    // Use Rc<UnsafeCell> so that clones share the same cell
152    inner: Rc<UnsafeCell<std::rc::Weak<T>>>,
153}
154
155impl<T: ?Sized> std::fmt::Debug for RcWeak<T> {
156    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157        f.debug_struct("RcWeak")
158            .field("strong_count", &self.strong_count())
159            .field("weak_count", &self.weak_count())
160            .finish()
161    }
162}
163
164impl<T> RcWeak<T> {
165    pub fn new() -> Self {
166        RcWeak {
167            inner: Rc::new(UnsafeCell::new(std::rc::Weak::new())),
168        }
169    }
170}
171
172impl<T: ?Sized> RcWeak<T> {
173    pub fn upgrade(&self) -> Option<Rc<T>> {
174        unsafe { (*self.inner.get()).upgrade() }
175    }
176
177    pub fn strong_count(&self) -> usize {
178        unsafe { (*self.inner.get()).strong_count() }
179    }
180
181    pub fn weak_count(&self) -> usize {
182        unsafe { (*self.inner.get()).weak_count() }
183    }
184
185    pub fn ptr_eq(&self, other: &Self) -> bool {
186        unsafe { std::rc::Weak::ptr_eq(&*self.inner.get(), &*other.inner.get()) }
187    }
188
189    pub fn update(&self, weak: std::rc::Weak<T>) {
190        unsafe {
191            *self.inner.get() = weak;
192        }
193    }
194
195    pub fn from_std(weak: std::rc::Weak<T>) -> Self {
196        RcWeak {
197            inner: Rc::new(UnsafeCell::new(weak)),
198        }
199    }
200}
201
202impl<T> Default for RcWeak<T> {
203    fn default() -> Self {
204        Self::new()
205    }
206}
207
208impl<T: ?Sized> Clone for RcWeak<T> {
209    fn clone(&self) -> Self {
210        // Clone the Rc, not the inner Weak - this way clones share the same cell!
211        RcWeak {
212            inner: self.inner.clone(),
213        }
214    }
215}
216
217impl<T: ?Sized> From<&Rc<T>> for RcWeak<T> {
218    fn from(rc: &Rc<T>) -> Self {
219        RcWeak::from_std(Rc::downgrade(rc))
220    }
221}
222
223unsafe impl<T: ?Sized> Send for RcWeak<T> where std::rc::Weak<T>: Send {}
224unsafe impl<T: ?Sized> Sync for RcWeak<T> where std::rc::Weak<T>: Sync {}
225
226/// A serializable wrapper around `std::sync::Weak<T>` (thread-safe).
227///
228/// `ArcWeak<T>` works exactly like [`RcWeak<T>`] but is intended for use with
229/// multi-threaded shared graphs where strong pointers are `Arc<T>`.
230///
231/// All clones of an `ArcWeak<T>` share the same `UnsafeCell` so deserialization
232/// updates propagate to all copies.
233///
234/// # Example
235/// See module-level docs for an `Arc<Mutex<Node>>` usage example.
236pub struct ArcWeak<T: ?Sized> {
237    // Use Arc<UnsafeCell> so that clones share the same cell
238    inner: Arc<UnsafeCell<std::sync::Weak<T>>>,
239}
240
241impl<T: ?Sized> std::fmt::Debug for ArcWeak<T> {
242    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243        f.debug_struct("ArcWeak")
244            .field("strong_count", &self.strong_count())
245            .field("weak_count", &self.weak_count())
246            .finish()
247    }
248}
249
250impl<T> ArcWeak<T> {
251    pub fn new() -> Self {
252        ArcWeak {
253            inner: Arc::new(UnsafeCell::new(std::sync::Weak::new())),
254        }
255    }
256}
257
258impl<T: ?Sized> ArcWeak<T> {
259    pub fn upgrade(&self) -> Option<Arc<T>> {
260        unsafe { (*self.inner.get()).upgrade() }
261    }
262
263    pub fn strong_count(&self) -> usize {
264        unsafe { (*self.inner.get()).strong_count() }
265    }
266
267    pub fn weak_count(&self) -> usize {
268        unsafe { (*self.inner.get()).weak_count() }
269    }
270
271    pub fn ptr_eq(&self, other: &Self) -> bool {
272        unsafe { std::sync::Weak::ptr_eq(&*self.inner.get(), &*other.inner.get()) }
273    }
274
275    pub fn update(&self, weak: std::sync::Weak<T>) {
276        unsafe {
277            *self.inner.get() = weak;
278        }
279    }
280
281    pub fn from_std(weak: std::sync::Weak<T>) -> Self {
282        ArcWeak {
283            inner: Arc::new(UnsafeCell::new(weak)),
284        }
285    }
286}
287
288impl<T> Default for ArcWeak<T> {
289    fn default() -> Self {
290        Self::new()
291    }
292}
293
294impl<T: ?Sized> Clone for ArcWeak<T> {
295    fn clone(&self) -> Self {
296        // Clone the Arc, not the inner Weak - this way clones share the same cell!
297        ArcWeak {
298            inner: self.inner.clone(),
299        }
300    }
301}
302
303impl<T: ?Sized> From<&Arc<T>> for ArcWeak<T> {
304    fn from(arc: &Arc<T>) -> Self {
305        ArcWeak::from_std(Arc::downgrade(arc))
306    }
307}
308
309unsafe impl<T: ?Sized + Send + Sync> Send for ArcWeak<T> {}
310unsafe impl<T: ?Sized + Send + Sync> Sync for ArcWeak<T> {}
311
312impl<T: Serializer + ForyDefault + 'static> Serializer for RcWeak<T> {
313    fn fory_is_shared_ref() -> bool {
314        true
315    }
316
317    fn fory_write(
318        &self,
319        context: &mut WriteContext,
320        write_ref_info: bool,
321        write_type_info: bool,
322        has_generics: bool,
323    ) -> Result<(), Error> {
324        if let Some(rc) = self.upgrade() {
325            if !write_ref_info
326                || !context
327                    .ref_writer
328                    .try_write_rc_ref(&mut context.writer, &rc)
329            {
330                if write_type_info {
331                    T::fory_write_type_info(context)?;
332                }
333                T::fory_write_data_generic(&*rc, context, has_generics)?;
334            }
335        } else {
336            ensure!(write_ref_info, "Value pointed by RcWeak<T> is null");
337
338            context.writer.write_i8(RefFlag::Null as i8);
339        }
340        Ok(())
341    }
342
343    fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
344        Err(Error::not_allowed(
345            "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
346        ))
347    }
348
349    fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
350        Err(Error::not_allowed(
351            "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
352        ))
353    }
354
355    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
356        T::fory_write_type_info(context)
357    }
358
359    fn fory_read(
360        context: &mut ReadContext,
361        read_ref_info: bool,
362        read_type_info: bool,
363    ) -> Result<Self, Error> {
364        read_rc_weak::<T>(context, read_ref_info, read_type_info, None)
365    }
366
367    fn fory_read_with_type_info(
368        context: &mut ReadContext,
369        read_ref_info: bool,
370        typeinfo: Rc<TypeInfo>,
371    ) -> Result<Self, Error> {
372        read_rc_weak::<T>(context, read_ref_info, false, Some(typeinfo))
373    }
374
375    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
376        Err(Error::not_allowed("RcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
377    }
378
379    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
380        T::fory_read_type_info(context)
381    }
382
383    fn fory_reserved_space() -> usize {
384        // RcWeak is a shared ref, return a const to avoid infinite recursion
385        4
386    }
387
388    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<u32, Error> {
389        T::fory_get_type_id(type_resolver)
390    }
391
392    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
393        if let Some(rc) = self.upgrade() {
394            (*rc).fory_type_id_dyn(type_resolver)
395        } else {
396            T::fory_get_type_id(type_resolver)
397        }
398    }
399
400    fn fory_static_type_id() -> TypeId {
401        T::fory_static_type_id()
402    }
403
404    fn as_any(&self) -> &dyn std::any::Any {
405        self
406    }
407}
408
409fn read_rc_weak<T: Serializer + ForyDefault + 'static>(
410    context: &mut ReadContext,
411    read_ref_info: bool,
412    read_type_info: bool,
413    type_info: Option<Rc<TypeInfo>>,
414) -> Result<RcWeak<T>, Error> {
415    let ref_flag = if read_ref_info {
416        context.ref_reader.read_ref_flag(&mut context.reader)?
417    } else {
418        RefFlag::NotNullValue
419    };
420    match ref_flag {
421        RefFlag::Null => Ok(RcWeak::new()),
422        RefFlag::RefValue => {
423            context.inc_depth()?;
424            let data = if let Some(type_info) = type_info {
425                T::fory_read_with_type_info(context, false, type_info)?
426            } else {
427                if read_type_info {
428                    context.read_any_typeinfo()?;
429                }
430                T::fory_read_data(context)?
431            };
432            context.dec_depth();
433            let rc = Rc::new(data);
434            let ref_id = context.ref_reader.store_rc_ref(rc);
435            let rc = context.ref_reader.get_rc_ref::<T>(ref_id).unwrap();
436            Ok(RcWeak::from(&rc))
437        }
438        RefFlag::Ref => {
439            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
440            if let Some(rc) = context.ref_reader.get_rc_ref::<T>(ref_id) {
441                Ok(RcWeak::from(&rc))
442            } else {
443                let result_weak = RcWeak::new();
444                let callback_weak = result_weak.clone();
445                context.ref_reader.add_callback(Box::new(move |ref_reader| {
446                    if let Some(rc) = ref_reader.get_rc_ref::<T>(ref_id) {
447                        callback_weak.update(Rc::downgrade(&rc));
448                    }
449                }));
450
451                Ok(result_weak)
452            }
453        }
454        RefFlag::NotNullValue => {
455            // let inner = if let Some(typeinfo) = type_info {
456            //     T::fory_read_with_type_info(context, false, typeinfo)?
457            // } else {
458            //     T::fory_read_data(context)?
459            // };
460            // Ok(RcWeak::from(&Rc::new(inner)))
461            Err(Error::invalid_ref("RcWeak can't hold a strong ref value"))
462        }
463    }
464}
465
466impl<T: ForyDefault> ForyDefault for RcWeak<T> {
467    fn fory_default() -> Self {
468        RcWeak::new()
469    }
470}
471
472impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for ArcWeak<T> {
473    fn fory_is_shared_ref() -> bool {
474        true
475    }
476
477    fn fory_write(
478        &self,
479        context: &mut WriteContext,
480        write_ref_info: bool,
481        write_type_info: bool,
482        has_generics: bool,
483    ) -> Result<(), Error> {
484        if let Some(arc) = self.upgrade() {
485            if !write_ref_info
486                || !context
487                    .ref_writer
488                    .try_write_arc_ref(&mut context.writer, &arc)
489            {
490                if write_type_info {
491                    T::fory_write_type_info(context)?;
492                }
493                T::fory_write_data_generic(&*arc, context, has_generics)?;
494            }
495        } else {
496            ensure!(write_ref_info, "Value pointed by ArcWeak<T> is null");
497            context.writer.write_i8(RefFlag::Null as i8);
498        }
499        Ok(())
500    }
501
502    fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
503        Err(Error::not_allowed(
504            "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
505        ))
506    }
507
508    fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
509        Err(Error::not_allowed(
510            "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
511        ))
512    }
513
514    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
515        T::fory_write_type_info(context)
516    }
517
518    fn fory_read(
519        context: &mut ReadContext,
520        read_ref_info: bool,
521        read_type_info: bool,
522    ) -> Result<Self, Error> {
523        read_arc_weak(context, read_ref_info, read_type_info, None)
524    }
525
526    fn fory_read_with_type_info(
527        context: &mut ReadContext,
528        read_ref_info: bool,
529        typeinfo: Rc<TypeInfo>,
530    ) -> Result<Self, Error> {
531        read_arc_weak::<T>(context, read_ref_info, false, Some(typeinfo))
532    }
533
534    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
535        Err(Error::not_allowed("ArcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
536    }
537
538    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
539        T::fory_read_type_info(context)
540    }
541
542    fn fory_reserved_space() -> usize {
543        // ArcWeak is a shared ref, return a const to avoid infinite recursion
544        4
545    }
546
547    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<u32, Error> {
548        T::fory_get_type_id(type_resolver)
549    }
550
551    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
552        if let Some(arc) = self.upgrade() {
553            (*arc).fory_type_id_dyn(type_resolver)
554        } else {
555            T::fory_get_type_id(type_resolver)
556        }
557    }
558
559    fn fory_static_type_id() -> TypeId {
560        T::fory_static_type_id()
561    }
562
563    fn as_any(&self) -> &dyn std::any::Any {
564        self
565    }
566}
567
568fn read_arc_weak<T: Serializer + ForyDefault + 'static>(
569    context: &mut ReadContext,
570    read_ref_info: bool,
571    read_type_info: bool,
572    type_info: Option<Rc<TypeInfo>>,
573) -> Result<ArcWeak<T>, Error> {
574    let ref_flag = if read_ref_info {
575        context.ref_reader.read_ref_flag(&mut context.reader)?
576    } else {
577        RefFlag::NotNullValue
578    };
579    match ref_flag {
580        RefFlag::Null => Ok(ArcWeak::new()),
581        RefFlag::RefValue => {
582            context.inc_depth()?;
583            let data = if let Some(type_info) = type_info {
584                T::fory_read_with_type_info(context, false, type_info)?
585            } else {
586                if read_type_info {
587                    context.read_any_typeinfo()?;
588                }
589                T::fory_read_data(context)?
590            };
591            context.dec_depth();
592            let arc = Arc::new(data);
593            let ref_id = context.ref_reader.store_arc_ref(arc);
594            let arc = context.ref_reader.get_arc_ref::<T>(ref_id).unwrap();
595            let weak = ArcWeak::from(&arc);
596            Ok(weak)
597        }
598        RefFlag::Ref => {
599            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
600            let weak = ArcWeak::new();
601
602            if let Some(arc) = context.ref_reader.get_arc_ref::<T>(ref_id) {
603                weak.update(Arc::downgrade(&arc));
604            } else {
605                // Capture the raw pointer to the UnsafeCell so we can update it in the callback
606                let weak_ptr = weak.inner.get();
607                context.ref_reader.add_callback(Box::new(move |ref_reader| {
608                    if let Some(arc) = ref_reader.get_arc_ref::<T>(ref_id) {
609                        unsafe {
610                            *weak_ptr = Arc::downgrade(&arc);
611                        }
612                    }
613                }));
614            }
615            Ok(weak)
616        }
617        RefFlag::NotNullValue => {
618            // let inner = if let Some(typeinfo) = type_info {
619            //     T::fory_read_with_type_info(context, false, typeinfo)?
620            // } else {
621            //     T::fory_read_data(context)?
622            // };
623            // Ok(ArcWeak::from(&Arc::new(inner)))
624            Err(Error::invalid_ref("ArcWeak can't hold a strong ref value"))
625        }
626    }
627}
628
629impl<T: ForyDefault> ForyDefault for ArcWeak<T> {
630    fn fory_default() -> Self {
631        ArcWeak::new()
632    }
633}