1use crate::context::{ReadContext, WriteContext};
21use crate::error::Error;
22use crate::resolver::{RefFlag, RefMode};
23use crate::resolver::{TypeInfo, TypeResolver};
24use crate::serializer::{ForyDefault, Serializer};
25use crate::type_id::TypeId;
26use crate::types::{ArcWeak, RcWeak};
27use std::rc::Rc;
28use std::sync::Arc;
29
30impl<T: Serializer + ForyDefault + 'static> Serializer for RcWeak<T> {
31 fn fory_is_shared_ref() -> bool {
32 true
33 }
34
35 fn fory_write(
36 &self,
37 context: &mut WriteContext,
38 ref_mode: RefMode,
39 write_type_info: bool,
40 has_generics: bool,
41 ) -> Result<(), Error> {
42 if !context.is_track_ref() {
44 return Err(Error::invalid_ref(
45 "RcWeak requires track_ref to be enabled. Use Fory::builder().track_ref(true).build()",
46 ));
47 }
48 if ref_mode != RefMode::Tracking {
50 return Err(Error::invalid_ref(
51 "RcWeak requires RefMode::Tracking for serialization",
52 ));
53 }
54 if let Some(rc) = self.upgrade() {
55 if !context
56 .ref_writer
57 .try_write_rc_ref(&mut context.writer, &rc)
58 {
59 if write_type_info {
60 T::fory_write_type_info(context)?;
61 }
62 T::fory_write_data_generic(&*rc, context, has_generics)?;
63 }
64 } else {
65 context.writer.write_i8(RefFlag::Null as i8);
66 }
67 Ok(())
68 }
69
70 fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
71 Err(Error::not_allowed(
72 "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
73 ))
74 }
75
76 fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
77 Err(Error::not_allowed(
78 "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
79 ))
80 }
81
82 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
83 T::fory_write_type_info(context)
84 }
85
86 fn fory_read(
87 context: &mut ReadContext,
88 ref_mode: RefMode,
89 read_type_info: bool,
90 ) -> Result<Self, Error> {
91 debug_assert!(
93 ref_mode == RefMode::Tracking,
94 "RcWeak requires RefMode::Tracking"
95 );
96 read_rc_weak::<T>(context, read_type_info, None)
97 }
98
99 fn fory_read_with_type_info(
100 context: &mut ReadContext,
101 ref_mode: RefMode,
102 typeinfo: Rc<TypeInfo>,
103 ) -> Result<Self, Error> {
104 debug_assert!(
105 ref_mode == RefMode::Tracking,
106 "RcWeak requires RefMode::Tracking"
107 );
108 read_rc_weak::<T>(context, false, Some(typeinfo))
109 }
110
111 fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
112 Err(Error::not_allowed("RcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
113 }
114
115 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
116 T::fory_read_type_info(context)
117 }
118
119 fn fory_reserved_space() -> usize {
120 4
122 }
123
124 fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
125 T::fory_get_type_id(type_resolver)
126 }
127
128 fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
129 T::fory_get_type_info(type_resolver)
130 }
131
132 fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
133 if let Some(rc) = self.upgrade() {
134 (*rc).fory_type_id_dyn(type_resolver)
135 } else {
136 T::fory_get_type_id(type_resolver)
137 }
138 }
139
140 fn fory_static_type_id() -> TypeId {
141 T::fory_static_type_id()
142 }
143
144 fn as_any(&self) -> &dyn std::any::Any {
145 self
146 }
147}
148
149fn read_rc_weak<T: Serializer + ForyDefault + 'static>(
150 context: &mut ReadContext,
151 read_type_info: bool,
152 type_info: Option<Rc<TypeInfo>>,
153) -> Result<RcWeak<T>, Error> {
154 let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
156 match ref_flag {
157 RefFlag::Null => Ok(RcWeak::new()),
158 RefFlag::RefValue => {
159 context.inc_depth()?;
160 let data = if let Some(type_info) = type_info {
161 T::fory_read_with_type_info(context, RefMode::None, type_info)?
162 } else {
163 if read_type_info {
164 context.read_any_type_info()?;
165 }
166 T::fory_read_data(context)?
167 };
168 context.dec_depth();
169 let rc = Rc::new(data);
170 let ref_id = context.ref_reader.store_rc_ref(rc);
171 let rc = context.ref_reader.get_rc_ref::<T>(ref_id).unwrap();
172 Ok(RcWeak::from(&rc))
173 }
174 RefFlag::Ref => {
175 let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
176 if let Some(rc) = context.ref_reader.get_rc_ref::<T>(ref_id) {
177 Ok(RcWeak::from(&rc))
178 } else {
179 let result_weak = RcWeak::new();
180 let callback_weak = result_weak.clone();
181 context.ref_reader.add_callback(Box::new(move |ref_reader| {
182 if let Some(rc) = ref_reader.get_rc_ref::<T>(ref_id) {
183 callback_weak.update(Rc::downgrade(&rc));
184 }
185 }));
186
187 Ok(result_weak)
188 }
189 }
190 RefFlag::NotNullValue => Err(Error::invalid_ref("RcWeak can't hold a strong ref value")),
191 }
192}
193
194impl<T: ForyDefault> ForyDefault for RcWeak<T> {
195 fn fory_default() -> Self {
196 RcWeak::new()
197 }
198}
199
200impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for ArcWeak<T> {
201 fn fory_is_shared_ref() -> bool {
202 true
203 }
204
205 fn fory_write(
206 &self,
207 context: &mut WriteContext,
208 ref_mode: RefMode,
209 write_type_info: bool,
210 has_generics: bool,
211 ) -> Result<(), Error> {
212 if !context.is_track_ref() {
214 return Err(Error::invalid_ref(
215 "ArcWeak requires track_ref to be enabled. Use Fory::builder().track_ref(true).build()",
216 ));
217 }
218 if ref_mode != RefMode::Tracking {
220 return Err(Error::invalid_ref(
221 "ArcWeak requires RefMode::Tracking for serialization",
222 ));
223 }
224 if let Some(arc) = self.upgrade() {
225 if !context
226 .ref_writer
227 .try_write_arc_ref(&mut context.writer, &arc)
228 {
229 if write_type_info {
230 T::fory_write_type_info(context)?;
231 }
232 T::fory_write_data_generic(&*arc, context, has_generics)?;
233 }
234 } else {
235 context.writer.write_i8(RefFlag::Null as i8);
236 }
237 Ok(())
238 }
239
240 fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
241 Err(Error::not_allowed(
242 "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
243 ))
244 }
245
246 fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
247 Err(Error::not_allowed(
248 "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
249 ))
250 }
251
252 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
253 T::fory_write_type_info(context)
254 }
255
256 fn fory_read(
257 context: &mut ReadContext,
258 ref_mode: RefMode,
259 read_type_info: bool,
260 ) -> Result<Self, Error> {
261 debug_assert!(
263 ref_mode == RefMode::Tracking,
264 "ArcWeak requires RefMode::Tracking"
265 );
266 read_arc_weak(context, read_type_info, None)
267 }
268
269 fn fory_read_with_type_info(
270 context: &mut ReadContext,
271 ref_mode: RefMode,
272 typeinfo: Rc<TypeInfo>,
273 ) -> Result<Self, Error> {
274 debug_assert!(
275 ref_mode == RefMode::Tracking,
276 "ArcWeak requires RefMode::Tracking"
277 );
278 read_arc_weak::<T>(context, false, Some(typeinfo))
279 }
280
281 fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
282 Err(Error::not_allowed("ArcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
283 }
284
285 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
286 T::fory_read_type_info(context)
287 }
288
289 fn fory_reserved_space() -> usize {
290 4
292 }
293
294 fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
295 T::fory_get_type_id(type_resolver)
296 }
297
298 fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
299 T::fory_get_type_info(type_resolver)
300 }
301
302 fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
303 if let Some(arc) = self.upgrade() {
304 (*arc).fory_type_id_dyn(type_resolver)
305 } else {
306 T::fory_get_type_id(type_resolver)
307 }
308 }
309
310 fn fory_static_type_id() -> TypeId {
311 T::fory_static_type_id()
312 }
313
314 fn as_any(&self) -> &dyn std::any::Any {
315 self
316 }
317}
318
319fn read_arc_weak<T: Serializer + ForyDefault + 'static>(
320 context: &mut ReadContext,
321 read_type_info: bool,
322 type_info: Option<Rc<TypeInfo>>,
323) -> Result<ArcWeak<T>, Error> {
324 let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
326 match ref_flag {
327 RefFlag::Null => Ok(ArcWeak::new()),
328 RefFlag::RefValue => {
329 context.inc_depth()?;
330 let data = if let Some(type_info) = type_info {
331 T::fory_read_with_type_info(context, RefMode::None, type_info)?
332 } else {
333 if read_type_info {
334 context.read_any_type_info()?;
335 }
336 T::fory_read_data(context)?
337 };
338 context.dec_depth();
339 let arc = Arc::new(data);
340 let ref_id = context.ref_reader.store_arc_ref(arc);
341 let arc = context.ref_reader.get_arc_ref::<T>(ref_id).unwrap();
342 let weak = ArcWeak::from(&arc);
343 Ok(weak)
344 }
345 RefFlag::Ref => {
346 let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
347 let weak = ArcWeak::new();
348
349 if let Some(arc) = context.ref_reader.get_arc_ref::<T>(ref_id) {
350 weak.update(Arc::downgrade(&arc));
351 } else {
352 let callback_weak = weak.clone();
353 context.ref_reader.add_callback(Box::new(move |ref_reader| {
354 if let Some(arc) = ref_reader.get_arc_ref::<T>(ref_id) {
355 callback_weak.update(Arc::downgrade(&arc));
356 }
357 }));
358 }
359 Ok(weak)
360 }
361 RefFlag::NotNullValue => Err(Error::invalid_ref("ArcWeak can't hold a strong ref value")),
362 }
363}
364
365impl<T: ForyDefault> ForyDefault for ArcWeak<T> {
366 fn fory_default() -> Self {
367 ArcWeak::new()
368 }
369}