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::error::Error;
19use crate::resolver::context::{ReadContext, WriteContext};
20use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
21use crate::serializer::{ForyDefault, Serializer};
22use crate::types::RefFlag;
23use crate::types::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        write_ref_info: bool,
35        write_type_info: bool,
36        has_generics: bool,
37    ) -> Result<(), Error> {
38        if !write_ref_info
39            || !context
40                .ref_writer
41                .try_write_rc_ref(&mut context.writer, self)
42        {
43            if T::fory_is_shared_ref() || T::fory_is_polymorphic() {
44                let inner_write_ref = T::fory_is_shared_ref();
45                return T::fory_write(
46                    &**self,
47                    context,
48                    inner_write_ref,
49                    write_type_info,
50                    has_generics,
51                );
52            }
53            if write_type_info {
54                T::fory_write_type_info(context)?;
55            }
56            T::fory_write_data_generic(self, context, has_generics)
57        } else {
58            Ok(())
59        }
60    }
61
62    fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
63        Err(Error::not_allowed(
64            "Rc<T> should be written using `fory_write` to handle reference tracking properly",
65        ))
66    }
67
68    fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
69        Err(Error::not_allowed(
70            "Rc<T> should be written using `fory_write` to handle reference tracking properly",
71        ))
72    }
73
74    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
75        T::fory_write_type_info(context)
76    }
77
78    fn fory_read(
79        context: &mut ReadContext,
80        read_ref_info: bool,
81        read_type_info: bool,
82    ) -> Result<Self, Error> {
83        read_rc(context, read_ref_info, read_type_info, None)
84    }
85
86    fn fory_read_with_type_info(
87        context: &mut ReadContext,
88        read_ref_info: bool,
89        typeinfo: Rc<TypeInfo>,
90    ) -> Result<Self, Error>
91    where
92        Self: Sized + ForyDefault,
93    {
94        read_rc(context, read_ref_info, false, Some(typeinfo))
95    }
96
97    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
98        Err(Error::not_allowed("Rc<T> should be read using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
99    }
100
101    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
102        T::fory_read_type_info(context)
103    }
104
105    fn fory_reserved_space() -> usize {
106        // Rc is a shared ref, so we just need space for the ref tracking
107        // We don't recursively compute inner type's space to avoid infinite recursion
108        4
109    }
110
111    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<u32, Error> {
112        T::fory_get_type_id(type_resolver)
113    }
114
115    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
116        (**self).fory_type_id_dyn(type_resolver)
117    }
118
119    fn fory_static_type_id() -> TypeId {
120        T::fory_static_type_id()
121    }
122
123    fn as_any(&self) -> &dyn std::any::Any {
124        self
125    }
126}
127
128fn read_rc<T: Serializer + ForyDefault + 'static>(
129    context: &mut ReadContext,
130    read_ref_info: bool,
131    read_type_info: bool,
132    typeinfo: Option<Rc<TypeInfo>>,
133) -> Result<Rc<T>, Error> {
134    let ref_flag = if read_ref_info {
135        context.ref_reader.read_ref_flag(&mut context.reader)?
136    } else {
137        RefFlag::NotNullValue
138    };
139    match ref_flag {
140        RefFlag::Null => Err(Error::invalid_ref("Rc cannot be null")),
141        RefFlag::Ref => {
142            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
143            context
144                .ref_reader
145                .get_rc_ref::<T>(ref_id)
146                .ok_or_else(|| Error::invalid_ref(format!("Rc reference {ref_id} not found")))
147        }
148        RefFlag::NotNullValue => {
149            let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
150            Ok(Rc::new(inner))
151        }
152        RefFlag::RefValue => {
153            let ref_id = context.ref_reader.reserve_ref_id();
154            let inner = read_rc_inner::<T>(context, read_type_info, typeinfo)?;
155            let rc = Rc::new(inner);
156            context.ref_reader.store_rc_ref_at(ref_id, rc.clone());
157            Ok(rc)
158        }
159    }
160}
161
162fn read_rc_inner<T: Serializer + ForyDefault + 'static>(
163    context: &mut ReadContext,
164    read_type_info: bool,
165    typeinfo: Option<Rc<TypeInfo>>,
166) -> Result<T, Error> {
167    if let Some(typeinfo) = typeinfo {
168        let inner_read_ref = T::fory_is_shared_ref();
169        return T::fory_read_with_type_info(context, inner_read_ref, typeinfo);
170    }
171    if T::fory_is_shared_ref() || T::fory_is_polymorphic() {
172        let inner_read_ref = T::fory_is_shared_ref();
173        return T::fory_read(context, inner_read_ref, read_type_info);
174    }
175    if read_type_info {
176        T::fory_read_type_info(context)?;
177    }
178    T::fory_read_data(context)
179}
180
181impl<T: ForyDefault> ForyDefault for Rc<T> {
182    fn fory_default() -> Self {
183        Rc::new(T::fory_default())
184    }
185}