Skip to main content

fory_core/serializer/
refcell.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//! Serialization support for `RefCell<T>`.
19//!
20//! This module implements `Serializer` and `ForyDefault` for `std::cell::RefCell<T>`.
21//! It allows mutable reference containers to be part of serialized graphs, which is often
22//! necessary when modeling object structures with interior mutability (e.g. parent/child links).
23//!
24//! Unlike `Rc` and `Arc`, `RefCell` does not do reference counting, so this wrapper relies
25//! on the serialization of the contained `T` only.
26//!
27//! This is commonly used together with `Rc<RefCell<T>>` in graph structures.
28//!
29//! # Example
30//! ```rust
31//! use std::cell::RefCell;
32//! let cell = RefCell::new(42);
33//! // Can be serialized by the Fory framework
34//! ```
35use crate::context::{ReadContext, WriteContext};
36use crate::error::Error;
37use crate::resolver::RefMode;
38use crate::resolver::{TypeInfo, TypeResolver};
39use crate::serializer::{ForyDefault, Serializer};
40use crate::type_id::TypeId;
41use std::cell::RefCell;
42use std::rc::Rc;
43
44/// `Serializer` impl for `RefCell<T>`
45///
46/// Simply delegates to the serializer for `T`, allowing interior mutable
47/// containers to be included in serialized graphs.
48impl<T: Serializer + ForyDefault> Serializer for RefCell<T> {
49    #[inline(always)]
50    fn fory_read(
51        context: &mut ReadContext,
52        ref_mode: RefMode,
53        read_type_info: bool,
54    ) -> Result<Self, Error>
55    where
56        Self: Sized + ForyDefault,
57    {
58        Ok(RefCell::new(T::fory_read(
59            context,
60            ref_mode,
61            read_type_info,
62        )?))
63    }
64
65    #[inline(always)]
66    fn fory_read_with_type_info(
67        context: &mut ReadContext,
68        ref_mode: RefMode,
69        type_info: Rc<TypeInfo>,
70    ) -> Result<Self, Error>
71    where
72        Self: Sized + ForyDefault,
73    {
74        Ok(RefCell::new(T::fory_read_with_type_info(
75            context, ref_mode, type_info,
76        )?))
77    }
78
79    #[inline(always)]
80    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
81        Ok(RefCell::new(T::fory_read_data(context)?))
82    }
83
84    #[inline(always)]
85    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
86        T::fory_read_type_info(context)
87    }
88
89    #[inline(always)]
90    fn fory_write(
91        &self,
92        context: &mut WriteContext,
93        ref_mode: RefMode,
94        write_type_info: bool,
95        has_generics: bool,
96    ) -> Result<(), Error> {
97        // Don't add ref tracking for RefCell itself, just delegate to inner type
98        // The inner type will handle its own ref tracking
99        T::fory_write(
100            &*self.borrow(),
101            context,
102            ref_mode,
103            write_type_info,
104            has_generics,
105        )
106    }
107
108    #[inline(always)]
109    fn fory_write_data_generic(
110        &self,
111        context: &mut WriteContext,
112        has_generics: bool,
113    ) -> Result<(), Error> {
114        T::fory_write_data_generic(&*self.borrow(), context, has_generics)
115    }
116
117    #[inline(always)]
118    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
119        T::fory_write_data(&*self.borrow(), context)
120    }
121
122    #[inline(always)]
123    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
124        T::fory_write_type_info(context)
125    }
126
127    #[inline(always)]
128    fn fory_reserved_space() -> usize {
129        // RefCell is transparent, delegate to inner type
130        T::fory_reserved_space()
131    }
132
133    #[inline(always)]
134    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
135        T::fory_get_type_id(type_resolver)
136    }
137
138    #[inline(always)]
139    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
140        T::fory_get_type_info(type_resolver)
141    }
142
143    #[inline(always)]
144    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
145        (*self.borrow()).fory_type_id_dyn(type_resolver)
146    }
147
148    #[inline(always)]
149    fn fory_static_type_id() -> TypeId
150    where
151        Self: Sized,
152    {
153        T::fory_static_type_id()
154    }
155
156    #[inline(always)]
157    fn fory_is_wrapper_type() -> bool
158    where
159        Self: Sized,
160    {
161        true
162    }
163
164    #[inline(always)]
165    fn as_any(&self) -> &dyn std::any::Any {
166        self
167    }
168}
169
170impl<T: ForyDefault> ForyDefault for RefCell<T> {
171    fn fory_default() -> Self {
172        RefCell::new(T::fory_default())
173    }
174}