Skip to main content

fory_core/serializer/
arc.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, RefMode, TypeId};
23use std::rc::Rc;
24use std::sync::Arc;
25
26impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for Arc<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_arc_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                "Arc<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_arc(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_arc(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                "Arc<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(Arc::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        // Arc 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        match type_resolver.get_type_info(&std::any::TypeId::of::<T>()) {
138            Ok(info) => Ok(info),
139            Err(e) => Err(Error::enhance_type_error::<T>(e)),
140        }
141    }
142
143    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
144        (**self).fory_type_id_dyn(type_resolver)
145    }
146
147    fn fory_static_type_id() -> TypeId {
148        T::fory_static_type_id()
149    }
150
151    fn as_any(&self) -> &dyn std::any::Any {
152        self
153    }
154}
155
156fn read_arc<T: Serializer + ForyDefault + 'static>(
157    context: &mut ReadContext,
158    ref_mode: RefMode,
159    read_type_info: bool,
160    typeinfo: Option<Rc<TypeInfo>>,
161) -> Result<Arc<T>, Error> {
162    match ref_mode {
163        RefMode::None => {
164            // No ref flag - read inner directly
165            let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
166            Ok(Arc::new(inner))
167        }
168        RefMode::NullOnly => {
169            // Read NotNullValue flag (Null not allowed for Arc)
170            let ref_flag = context.reader.read_i8()?;
171            if ref_flag == RefFlag::Null as i8 {
172                return Err(Error::invalid_ref("Arc cannot be null"));
173            }
174            let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
175            Ok(Arc::new(inner))
176        }
177        RefMode::Tracking => {
178            // Full ref tracking
179            let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
180            match ref_flag {
181                RefFlag::Null => Err(Error::invalid_ref("Arc cannot be null")),
182                RefFlag::Ref => {
183                    let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
184                    context.ref_reader.get_arc_ref::<T>(ref_id).ok_or_else(|| {
185                        Error::invalid_ref(format!("Arc reference {ref_id} not found"))
186                    })
187                }
188                RefFlag::NotNullValue => {
189                    let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
190                    Ok(Arc::new(inner))
191                }
192                RefFlag::RefValue => {
193                    let ref_id = context.ref_reader.reserve_ref_id();
194                    let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
195                    let arc = Arc::new(inner);
196                    context.ref_reader.store_arc_ref_at(ref_id, arc.clone());
197                    Ok(arc)
198                }
199            }
200        }
201    }
202}
203
204fn read_arc_inner<T: Serializer + ForyDefault + 'static>(
205    context: &mut ReadContext,
206    read_type_info: bool,
207    typeinfo: Option<Rc<TypeInfo>>,
208) -> Result<T, Error> {
209    // Read type info if needed, then read data directly
210    // No recursive ref handling needed since Arc<T> only wraps allowed types
211    if let Some(typeinfo) = typeinfo {
212        return T::fory_read_with_type_info(context, RefMode::None, typeinfo);
213    }
214    if read_type_info {
215        T::fory_read_type_info(context)?;
216    }
217    T::fory_read_data(context)
218}
219
220impl<T: ForyDefault> ForyDefault for Arc<T> {
221    fn fory_default() -> Self {
222        Arc::new(T::fory_default())
223    }
224}