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