Skip to main content

fory_core/serializer/
rc.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::context::{ReadContext, WriteContext};
19use crate::error::Error;
20use crate::resolver::{RefFlag, RefMode};
21use crate::resolver::{TypeInfo, TypeResolver};
22use crate::serializer::{ForyDefault, Serializer};
23use crate::type_id::TypeId;
24use std::rc::Rc;
25
26impl<T: Serializer + ForyDefault + 'static> Serializer for Rc<T> {
27    fn fory_is_shared_ref() -> bool {
28        true
29    }
30
31    fn fory_write(
32        &self,
33        context: &mut WriteContext,
34        ref_mode: RefMode,
35        write_type_info: bool,
36        has_generics: bool,
37    ) -> Result<(), Error> {
38        match ref_mode {
39            RefMode::None => {
40                // No ref flag - write inner directly
41                if write_type_info {
42                    T::fory_write_type_info(context)?;
43                }
44                T::fory_write_data_generic(self, context, has_generics)
45            }
46            RefMode::NullOnly => {
47                // Only null check, no ref tracking
48                context.writer.write_i8(RefFlag::NotNullValue as i8);
49                if write_type_info {
50                    T::fory_write_type_info(context)?;
51                }
52                T::fory_write_data_generic(self, context, has_generics)
53            }
54            RefMode::Tracking => {
55                // Full ref tracking with RefWriter
56                if context
57                    .ref_writer
58                    .try_write_rc_ref(&mut context.writer, self)
59                {
60                    // Already written as ref - done
61                    return Ok(());
62                }
63                // First occurrence - write type info and data
64                if write_type_info {
65                    T::fory_write_type_info(context)?;
66                }
67                T::fory_write_data_generic(self, context, has_generics)
68            }
69        }
70    }
71
72    fn fory_write_data_generic(
73        &self,
74        context: &mut WriteContext,
75        has_generics: bool,
76    ) -> Result<(), Error> {
77        if T::fory_is_shared_ref() {
78            return Err(Error::not_allowed(
79                "Rc<T> where T is a shared ref type is not allowed for serialization.",
80            ));
81        }
82        T::fory_write_data_generic(&**self, context, has_generics)
83    }
84
85    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
86        self.fory_write_data_generic(context, false)
87    }
88
89    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
90        T::fory_write_type_info(context)
91    }
92
93    fn fory_read(
94        context: &mut ReadContext,
95        ref_mode: RefMode,
96        read_type_info: bool,
97    ) -> Result<Self, Error> {
98        read_rc(context, ref_mode, read_type_info, None)
99    }
100
101    fn fory_read_with_type_info(
102        context: &mut ReadContext,
103        ref_mode: RefMode,
104        typeinfo: Rc<TypeInfo>,
105    ) -> Result<Self, Error>
106    where
107        Self: Sized + ForyDefault,
108    {
109        read_rc(context, ref_mode, false, Some(typeinfo))
110    }
111
112    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
113        if T::fory_is_shared_ref() {
114            return Err(Error::not_allowed(
115                "Rc<T> where T is a shared ref type is not allowed for deserialization.",
116            ));
117        }
118        let inner = T::fory_read_data(context)?;
119        Ok(Rc::new(inner))
120    }
121
122    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
123        T::fory_read_type_info(context)
124    }
125
126    fn fory_reserved_space() -> usize {
127        // Rc is a shared ref, so we just need space for the ref tracking
128        // We don't recursively compute inner type's space to avoid infinite recursion
129        4
130    }
131
132    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
133        T::fory_get_type_id(type_resolver)
134    }
135
136    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
137        T::fory_get_type_info(type_resolver)
138    }
139
140    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
141        (**self).fory_type_id_dyn(type_resolver)
142    }
143
144    fn fory_static_type_id() -> TypeId {
145        T::fory_static_type_id()
146    }
147
148    fn as_any(&self) -> &dyn std::any::Any {
149        self
150    }
151}
152
153fn read_rc<T: Serializer + ForyDefault + 'static>(
154    context: &mut ReadContext,
155    ref_mode: RefMode,
156    read_type_info: bool,
157    typeinfo: Option<Rc<TypeInfo>>,
158) -> Result<Rc<T>, Error> {
159    match ref_mode {
160        RefMode::None => {
161            // No ref flag - read inner directly
162            let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
163            Ok(Rc::new(inner))
164        }
165        RefMode::NullOnly => {
166            // Read NotNullValue flag (Null not allowed for Rc)
167            let ref_flag = context.reader.read_i8()?;
168            if ref_flag == RefFlag::Null as i8 {
169                return Err(Error::invalid_ref("Rc cannot be null"));
170            }
171            let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
172            Ok(Rc::new(inner))
173        }
174        RefMode::Tracking => {
175            // Full ref tracking
176            let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
177            match ref_flag {
178                RefFlag::Null => Err(Error::invalid_ref("Rc cannot be null")),
179                RefFlag::Ref => {
180                    let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
181                    context.ref_reader.get_rc_ref::<T>(ref_id).ok_or_else(|| {
182                        Error::invalid_ref(format!("Rc reference {ref_id} not found"))
183                    })
184                }
185                RefFlag::NotNullValue => {
186                    let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
187                    Ok(Rc::new(inner))
188                }
189                RefFlag::RefValue => {
190                    let ref_id = context.ref_reader.reserve_ref_id();
191                    let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
192                    let rc = Rc::new(inner);
193                    context.ref_reader.store_rc_ref_at(ref_id, rc.clone());
194                    Ok(rc)
195                }
196            }
197        }
198    }
199}
200
201fn read_rc_inner<T: Serializer + ForyDefault + 'static>(
202    context: &mut ReadContext,
203    read_type_info: bool,
204    typeinfo: Option<Rc<TypeInfo>>,
205) -> Result<T, Error> {
206    // Read type info if needed, then read data directly
207    // No recursive ref handling needed since Rc<T> only wraps allowed types
208    if let Some(typeinfo) = typeinfo {
209        return T::fory_read_with_type_info(context, RefMode::None, typeinfo);
210    }
211    if read_type_info {
212        T::fory_read_type_info(context)?;
213    }
214    T::fory_read_data(context)
215}
216
217impl<T: ForyDefault> ForyDefault for Rc<T> {
218    fn fory_default() -> Self {
219        Rc::new(T::fory_default())
220    }
221}