Skip to main content

fory_core/serializer/
weak.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
18//! Serialization support for [`RcWeak`] and [`ArcWeak`].
19
20use super::codec::{codec_read_type_info, codec_read_type_info_static, Codec};
21use crate::context::{ReadContext, WriteContext};
22use crate::error::Error;
23use crate::meta::FieldType;
24use crate::resolver::{RefFlag, RefMode, TypeInfo, TypeResolver};
25use crate::serializer::Serializer;
26use crate::type_id::TypeId;
27use crate::types::{ArcWeak, RcWeak};
28use std::marker::PhantomData;
29use std::rc::Rc;
30use std::sync::Arc;
31
32pub struct RcWeakCodec<T, C, const NULLABLE: bool, const TRACK_REF: bool>(PhantomData<(T, C)>);
33
34pub struct ArcWeakCodec<T, C, const NULLABLE: bool, const TRACK_REF: bool>(PhantomData<(T, C)>);
35
36#[inline(always)]
37fn reserve_weak_cell<W>(context: &mut ReadContext) -> Result<(), Error> {
38    let bytes = std::mem::size_of::<W>();
39    if bytes != 0 {
40        context.reserve_graph_memory(bytes)?;
41    }
42    Ok(())
43}
44
45#[inline(always)]
46fn reserve_strong<T>(context: &mut ReadContext) -> Result<(), Error> {
47    let bytes = std::mem::size_of::<T>();
48    if bytes != 0 {
49        context.reserve_graph_memory(bytes)?;
50    }
51    Ok(())
52}
53
54#[cold]
55#[inline(never)]
56fn rc_weak_tracking_error() -> Error {
57    Error::invalid_ref(
58        "RcWeak requires track_ref to be enabled. \
59         Use Fory::builder().track_ref(true).build()",
60    )
61}
62
63#[cold]
64#[inline(never)]
65fn arc_weak_tracking_error() -> Error {
66    Error::invalid_ref(
67        "ArcWeak requires track_ref to be enabled. \
68         Use Fory::builder().track_ref(true).build()",
69    )
70}
71
72#[cold]
73#[inline(never)]
74fn weak_write_mode_error(owner: &str) -> Error {
75    Error::invalid_ref(format!(
76        "{owner} requires RefMode::Tracking for serialization"
77    ))
78}
79
80#[cold]
81#[inline(never)]
82fn weak_read_mode_error(owner: &str) -> Error {
83    Error::invalid_ref(format!(
84        "{owner} requires RefMode::Tracking for deserialization"
85    ))
86}
87
88#[cold]
89#[inline(never)]
90fn weak_untracked_value(owner: &str) -> Error {
91    Error::invalid_ref(format!("{owner} cannot contain an untracked strong value"))
92}
93
94#[inline(always)]
95fn rc_weak_body<T: 'static>(
96    value: &RcWeak<T>,
97    context: &mut WriteContext,
98    ref_mode: RefMode,
99) -> Result<Option<Rc<T>>, Error> {
100    if !context.is_track_ref() {
101        return Err(rc_weak_tracking_error());
102    }
103    if ref_mode != RefMode::Tracking {
104        return Err(weak_write_mode_error("RcWeak"));
105    }
106    let Some(value) = value.upgrade() else {
107        context.writer.write_i8(RefFlag::Null as i8);
108        return Ok(None);
109    };
110    if context
111        .ref_writer
112        .try_write_rc_ref(&mut context.writer, &value)
113    {
114        return Ok(None);
115    }
116    Ok(Some(value))
117}
118
119#[inline(always)]
120fn write_rc_weak<T: 'static, C: Serializer<Target = T>>(
121    value: &RcWeak<T>,
122    context: &mut WriteContext,
123    ref_mode: RefMode,
124    write_type_info: bool,
125) -> Result<(), Error> {
126    let Some(value) = rc_weak_body(value, context, ref_mode)? else {
127        return Ok(());
128    };
129    C::write(&value, context, RefMode::None, write_type_info)
130}
131
132#[inline(always)]
133fn write_rc_weak_field<T: 'static, C: Codec<T>>(
134    value: &RcWeak<T>,
135    context: &mut WriteContext,
136    ref_mode: RefMode,
137    write_type_info: bool,
138    has_generics: bool,
139) -> Result<(), Error> {
140    let Some(value) = rc_weak_body(value, context, ref_mode)? else {
141        return Ok(());
142    };
143    C::write_with_mode(
144        &value,
145        context,
146        RefMode::None,
147        write_type_info,
148        has_generics,
149    )
150}
151
152#[inline(always)]
153fn write_rc_weak_with_type_info<T: 'static, C: Serializer<Target = T>>(
154    value: &RcWeak<T>,
155    context: &mut WriteContext,
156    ref_mode: RefMode,
157    type_info: &Rc<TypeInfo>,
158) -> Result<(), Error> {
159    let Some(value) = rc_weak_body(value, context, ref_mode)? else {
160        return Ok(());
161    };
162    C::write_with_type_info(&value, context, RefMode::None, type_info)
163}
164
165#[inline(always)]
166fn write_rc_weak_field_with_type_info<T: 'static, C: Codec<T>>(
167    value: &RcWeak<T>,
168    context: &mut WriteContext,
169    ref_mode: RefMode,
170    type_info: &Rc<TypeInfo>,
171    has_generics: bool,
172) -> Result<(), Error> {
173    let Some(value) = rc_weak_body(value, context, ref_mode)? else {
174        return Ok(());
175    };
176    <C as Codec<T>>::write_with_type_info(&value, context, RefMode::None, type_info, has_generics)
177}
178
179#[inline(always)]
180fn read_rc_inner<T: 'static, C: Serializer<Target = T>>(
181    context: &mut ReadContext,
182    read_type_info: bool,
183    type_info: Option<&Rc<TypeInfo>>,
184) -> Result<T, Error> {
185    reserve_strong::<T>(context)?;
186    if let Some(type_info) = type_info {
187        return C::read_with_type_info(context, RefMode::None, type_info);
188    }
189    // The weak envelope has consumed its ref flag; the child still owns any
190    // inline dynamic metadata before its body.
191    C::read(context, RefMode::None, read_type_info)
192}
193
194#[inline(always)]
195fn read_rc_inner_with_type<T: 'static, C: Codec<T>>(
196    context: &mut ReadContext,
197    remote_field_type: &FieldType,
198) -> Result<T, Error> {
199    reserve_strong::<T>(context)?;
200    // The weak envelope owns only reference framing. A compatible
201    // metadata-bearing child still owns its inline TypeInfo before its body,
202    // while declared carrier children consume the remote schema directly.
203    if codec_read_type_info::<T, C>(context, remote_field_type) {
204        return C::read(context, RefMode::None, true);
205    }
206    C::read_data_with_type(context, remote_field_type)
207}
208
209macro_rules! read_rc_weak_owner {
210    ($context:ident, $ref_mode:expr, $read_inner:expr) => {{
211        if $ref_mode != RefMode::Tracking {
212            return Err(weak_read_mode_error("RcWeak"));
213        }
214        match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
215            RefFlag::Null => {
216                reserve_weak_cell::<std::rc::Weak<T>>($context)?;
217                Ok(RcWeak::new())
218            }
219            RefFlag::RefValue => {
220                // The writer assigns the strong target's ID before its body.
221                // Reserve that slot now, but publish only the final Rc after
222                // the complete child read succeeds.
223                let ref_id = $context.ref_reader.reserve_ref_id();
224                $context.inc_depth()?;
225                let value = $read_inner?;
226                $context.dec_depth();
227                let strong = Rc::new(value);
228                reserve_weak_cell::<std::rc::Weak<T>>($context)?;
229                $context.ref_reader.store_rc_ref_at(ref_id, strong.clone());
230                Ok(RcWeak::from(&strong))
231            }
232            RefFlag::Ref => {
233                let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
234                reserve_weak_cell::<std::rc::Weak<T>>($context)?;
235                if let Some(strong) = $context.ref_reader.get_rc_ref::<T>(ref_id) {
236                    return Ok(RcWeak::from(&strong));
237                }
238                let weak = RcWeak::new();
239                let callback_weak = weak.clone();
240                $context.ref_reader.add_callback(Box::new(move |reader| {
241                    if let Some(strong) = reader.get_rc_ref::<T>(ref_id) {
242                        callback_weak.update(Rc::downgrade(&strong));
243                    }
244                }));
245                Ok(weak)
246            }
247            RefFlag::NotNullValue => Err(weak_untracked_value("RcWeak")),
248        }
249    }};
250}
251
252#[inline(always)]
253fn read_rc_weak<T: 'static, C: Serializer<Target = T>>(
254    context: &mut ReadContext,
255    ref_mode: RefMode,
256    read_type_info: bool,
257    type_info: Option<&Rc<TypeInfo>>,
258) -> Result<RcWeak<T>, Error> {
259    read_rc_weak_owner!(
260        context,
261        ref_mode,
262        read_rc_inner::<T, C>(context, read_type_info, type_info)
263    )
264}
265
266#[inline(always)]
267fn read_rc_weak_with_type<T: 'static, C: Codec<T>>(
268    context: &mut ReadContext,
269    ref_mode: RefMode,
270    remote_field_type: &FieldType,
271) -> Result<RcWeak<T>, Error> {
272    read_rc_weak_owner!(
273        context,
274        ref_mode,
275        read_rc_inner_with_type::<T, C>(context, remote_field_type)
276    )
277}
278
279impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
280    for RcWeakCodec<T, C, NULLABLE, TRACK_REF>
281where
282    T: 'static,
283    C: Serializer<Target = T>,
284{
285    type Target = RcWeak<T>;
286
287    #[inline(always)]
288    fn reserved_space() -> usize {
289        4
290    }
291
292    #[cold]
293    #[inline(never)]
294    fn write_data(_: &RcWeak<T>, _: &mut WriteContext) -> Result<(), Error> {
295        Err(Error::not_allowed(
296            "RcWeak must be written through its reference-tracking envelope",
297        ))
298    }
299
300    #[cold]
301    #[inline(never)]
302    fn read_data(_: &mut ReadContext) -> Result<RcWeak<T>, Error> {
303        Err(Error::not_allowed(
304            "RcWeak must be read through its reference-tracking envelope",
305        ))
306    }
307
308    #[inline(always)]
309    fn write(
310        value: &RcWeak<T>,
311        context: &mut WriteContext,
312        ref_mode: RefMode,
313        write_type_info: bool,
314    ) -> Result<(), Error> {
315        write_rc_weak::<T, C>(value, context, ref_mode, write_type_info)
316    }
317
318    #[inline(always)]
319    fn write_type_info_value(
320        context: &mut WriteContext,
321        target_type_id: std::any::TypeId,
322    ) -> Result<Rc<TypeInfo>, Error> {
323        C::write_type_info_value(context, target_type_id)
324    }
325
326    #[inline(always)]
327    fn write_with_type_info(
328        value: &RcWeak<T>,
329        context: &mut WriteContext,
330        ref_mode: RefMode,
331        type_info: &Rc<TypeInfo>,
332    ) -> Result<(), Error> {
333        write_rc_weak_with_type_info::<T, C>(value, context, ref_mode, type_info)
334    }
335
336    #[inline(always)]
337    fn read(
338        context: &mut ReadContext,
339        ref_mode: RefMode,
340        read_type_info: bool,
341    ) -> Result<RcWeak<T>, Error> {
342        read_rc_weak::<T, C>(context, ref_mode, read_type_info, None)
343    }
344
345    #[inline(always)]
346    fn read_with_type_info(
347        context: &mut ReadContext,
348        ref_mode: RefMode,
349        type_info: &Rc<TypeInfo>,
350    ) -> Result<RcWeak<T>, Error> {
351        read_rc_weak::<T, C>(context, ref_mode, false, Some(type_info))
352    }
353
354    #[inline(always)]
355    fn default_value(context: &mut ReadContext) -> Result<RcWeak<T>, Error> {
356        reserve_weak_cell::<std::rc::Weak<T>>(context)?;
357        Ok(RcWeak::new())
358    }
359
360    #[inline(always)]
361    fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
362        C::write_type_info(context)
363    }
364
365    #[inline(always)]
366    fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
367        C::read_type_info(context)
368    }
369
370    #[inline(always)]
371    fn static_type_id() -> TypeId {
372        C::static_type_id()
373    }
374
375    #[inline(always)]
376    fn metadata_target_type_id() -> std::any::TypeId {
377        C::metadata_target_type_id()
378    }
379
380    const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
381
382    const IS_SHARED_REF: bool = true;
383
384    const IS_WRAPPER: bool = true;
385
386    const REQUIRES_SCOPED_ACCESS: bool = true;
387
388    #[inline(always)]
389    fn dynamic_type_id(value: &RcWeak<T>) -> Result<Option<std::any::TypeId>, Error> {
390        match value.upgrade() {
391            Some(value) => C::dynamic_type_id(&value),
392            None => Ok(None),
393        }
394    }
395}
396
397impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<RcWeak<T>>
398    for RcWeakCodec<T, C, NULLABLE, TRACK_REF>
399where
400    T: 'static,
401    C: Codec<T>,
402{
403    #[inline(always)]
404    fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
405        let mut field_type = C::field_type(type_resolver)?;
406        field_type.nullable = NULLABLE;
407        field_type.track_ref = true;
408        Ok(field_type)
409    }
410
411    #[inline(always)]
412    fn write_field(value: &RcWeak<T>, context: &mut WriteContext) -> Result<(), Error> {
413        Self::write_with_mode(
414            value,
415            context,
416            RefMode::Tracking,
417            super::codec::codec_write_type_info::<T, C>(context),
418            true,
419        )
420    }
421
422    #[inline(always)]
423    fn read_field(context: &mut ReadContext) -> Result<RcWeak<T>, Error> {
424        <Self as Serializer>::read(
425            context,
426            RefMode::Tracking,
427            codec_read_type_info_static::<T, C>(context),
428        )
429    }
430
431    #[inline(always)]
432    fn read_field_with_type(
433        context: &mut ReadContext,
434        remote_field_type: &FieldType,
435    ) -> Result<RcWeak<T>, Error> {
436        read_rc_weak_with_type::<T, C>(context, RefMode::Tracking, remote_field_type)
437    }
438
439    #[inline(always)]
440    fn write_with_mode(
441        value: &RcWeak<T>,
442        context: &mut WriteContext,
443        ref_mode: RefMode,
444        write_type_info: bool,
445        has_generics: bool,
446    ) -> Result<(), Error> {
447        write_rc_weak_field::<T, C>(value, context, ref_mode, write_type_info, has_generics)
448    }
449
450    #[inline(always)]
451    fn write_with_type_info(
452        value: &RcWeak<T>,
453        context: &mut WriteContext,
454        ref_mode: RefMode,
455        type_info: &Rc<TypeInfo>,
456        has_generics: bool,
457    ) -> Result<(), Error> {
458        write_rc_weak_field_with_type_info::<T, C>(
459            value,
460            context,
461            ref_mode,
462            type_info,
463            has_generics,
464        )
465    }
466
467    #[inline(always)]
468    fn read_type_info_value(
469        context: &mut ReadContext,
470    ) -> Result<super::codec::CodecReadType, Error> {
471        C::read_type_info_value(context)
472    }
473}
474
475#[inline(always)]
476fn arc_weak_body<T: Send + Sync + 'static>(
477    value: &ArcWeak<T>,
478    context: &mut WriteContext,
479    ref_mode: RefMode,
480) -> Result<Option<Arc<T>>, Error> {
481    if !context.is_track_ref() {
482        return Err(arc_weak_tracking_error());
483    }
484    if ref_mode != RefMode::Tracking {
485        return Err(weak_write_mode_error("ArcWeak"));
486    }
487    let Some(value) = value.upgrade() else {
488        context.writer.write_i8(RefFlag::Null as i8);
489        return Ok(None);
490    };
491    if context
492        .ref_writer
493        .try_write_arc_ref(&mut context.writer, &value)
494    {
495        return Ok(None);
496    }
497    Ok(Some(value))
498}
499
500#[inline(always)]
501fn write_arc_weak<T: Send + Sync + 'static, C: Serializer<Target = T>>(
502    value: &ArcWeak<T>,
503    context: &mut WriteContext,
504    ref_mode: RefMode,
505    write_type_info: bool,
506) -> Result<(), Error> {
507    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
508        return Ok(());
509    };
510    C::write(&value, context, RefMode::None, write_type_info)
511}
512
513#[inline(always)]
514fn write_arc_weak_field<T: Send + Sync + 'static, C: Codec<T>>(
515    value: &ArcWeak<T>,
516    context: &mut WriteContext,
517    ref_mode: RefMode,
518    write_type_info: bool,
519    has_generics: bool,
520) -> Result<(), Error> {
521    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
522        return Ok(());
523    };
524    C::write_with_mode(
525        &value,
526        context,
527        RefMode::None,
528        write_type_info,
529        has_generics,
530    )
531}
532
533#[inline(always)]
534fn write_arc_weak_with_type_info<T: Send + Sync + 'static, C: Serializer<Target = T>>(
535    value: &ArcWeak<T>,
536    context: &mut WriteContext,
537    ref_mode: RefMode,
538    type_info: &Rc<TypeInfo>,
539) -> Result<(), Error> {
540    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
541        return Ok(());
542    };
543    C::write_with_type_info(&value, context, RefMode::None, type_info)
544}
545
546#[inline(always)]
547fn write_arc_weak_field_with_type_info<T: Send + Sync + 'static, C: Codec<T>>(
548    value: &ArcWeak<T>,
549    context: &mut WriteContext,
550    ref_mode: RefMode,
551    type_info: &Rc<TypeInfo>,
552    has_generics: bool,
553) -> Result<(), Error> {
554    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
555        return Ok(());
556    };
557    <C as Codec<T>>::write_with_type_info(&value, context, RefMode::None, type_info, has_generics)
558}
559
560#[inline(always)]
561fn read_arc_inner<T: Send + Sync + 'static, C: Serializer<Target = T>>(
562    context: &mut ReadContext,
563    read_type_info: bool,
564    type_info: Option<&Rc<TypeInfo>>,
565) -> Result<T, Error> {
566    reserve_strong::<T>(context)?;
567    if let Some(type_info) = type_info {
568        return C::read_with_type_info(context, RefMode::None, type_info);
569    }
570    // The weak envelope has consumed its ref flag; the child still owns any
571    // inline dynamic metadata before its body.
572    C::read(context, RefMode::None, read_type_info)
573}
574
575#[inline(always)]
576fn read_arc_inner_with_type<T: Send + Sync + 'static, C: Codec<T>>(
577    context: &mut ReadContext,
578    remote_field_type: &FieldType,
579) -> Result<T, Error> {
580    reserve_strong::<T>(context)?;
581    // The weak envelope owns only reference framing. A compatible
582    // metadata-bearing child still owns its inline TypeInfo before its body,
583    // while declared carrier children consume the remote schema directly.
584    if codec_read_type_info::<T, C>(context, remote_field_type) {
585        return C::read(context, RefMode::None, true);
586    }
587    C::read_data_with_type(context, remote_field_type)
588}
589
590macro_rules! read_arc_weak_owner {
591    ($context:ident, $ref_mode:expr, $read_inner:expr) => {{
592        if $ref_mode != RefMode::Tracking {
593            return Err(weak_read_mode_error("ArcWeak"));
594        }
595        match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
596            RefFlag::Null => {
597                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
598                Ok(ArcWeak::new())
599            }
600            RefFlag::RefValue => {
601                // The writer assigns the strong target's ID before its body.
602                // Reserve that slot now, but publish only the final Arc after
603                // the complete child read succeeds.
604                let ref_id = $context.ref_reader.reserve_ref_id();
605                $context.inc_depth()?;
606                let value = $read_inner?;
607                $context.dec_depth();
608                let strong = Arc::new(value);
609                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
610                $context.ref_reader.store_arc_ref_at(ref_id, strong.clone());
611                Ok(ArcWeak::from(&strong))
612            }
613            RefFlag::Ref => {
614                let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
615                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
616                let weak = ArcWeak::new();
617                if let Some(strong) = $context.ref_reader.get_arc_ref::<T>(ref_id) {
618                    weak.update(Arc::downgrade(&strong));
619                } else {
620                    let callback_weak = weak.clone();
621                    $context.ref_reader.add_callback(Box::new(move |reader| {
622                        if let Some(strong) = reader.get_arc_ref::<T>(ref_id) {
623                            callback_weak.update(Arc::downgrade(&strong));
624                        }
625                    }));
626                }
627                Ok(weak)
628            }
629            RefFlag::NotNullValue => Err(weak_untracked_value("ArcWeak")),
630        }
631    }};
632}
633
634#[inline(always)]
635fn read_arc_weak<T: Send + Sync + 'static, C: Serializer<Target = T>>(
636    context: &mut ReadContext,
637    ref_mode: RefMode,
638    read_type_info: bool,
639    type_info: Option<&Rc<TypeInfo>>,
640) -> Result<ArcWeak<T>, Error> {
641    read_arc_weak_owner!(
642        context,
643        ref_mode,
644        read_arc_inner::<T, C>(context, read_type_info, type_info)
645    )
646}
647
648#[inline(always)]
649fn read_arc_weak_with_type<T: Send + Sync + 'static, C: Codec<T>>(
650    context: &mut ReadContext,
651    ref_mode: RefMode,
652    remote_field_type: &FieldType,
653) -> Result<ArcWeak<T>, Error> {
654    read_arc_weak_owner!(
655        context,
656        ref_mode,
657        read_arc_inner_with_type::<T, C>(context, remote_field_type)
658    )
659}
660
661impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
662    for ArcWeakCodec<T, C, NULLABLE, TRACK_REF>
663where
664    T: Send + Sync + 'static,
665    C: Serializer<Target = T>,
666{
667    type Target = ArcWeak<T>;
668
669    #[inline(always)]
670    fn reserved_space() -> usize {
671        4
672    }
673
674    #[cold]
675    #[inline(never)]
676    fn write_data(_: &ArcWeak<T>, _: &mut WriteContext) -> Result<(), Error> {
677        Err(Error::not_allowed(
678            "ArcWeak must be written through its reference-tracking envelope",
679        ))
680    }
681
682    #[cold]
683    #[inline(never)]
684    fn read_data(_: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
685        Err(Error::not_allowed(
686            "ArcWeak must be read through its reference-tracking envelope",
687        ))
688    }
689
690    #[inline(always)]
691    fn write(
692        value: &ArcWeak<T>,
693        context: &mut WriteContext,
694        ref_mode: RefMode,
695        write_type_info: bool,
696    ) -> Result<(), Error> {
697        write_arc_weak::<T, C>(value, context, ref_mode, write_type_info)
698    }
699
700    #[inline(always)]
701    fn write_type_info_value(
702        context: &mut WriteContext,
703        target_type_id: std::any::TypeId,
704    ) -> Result<Rc<TypeInfo>, Error> {
705        C::write_type_info_value(context, target_type_id)
706    }
707
708    #[inline(always)]
709    fn write_with_type_info(
710        value: &ArcWeak<T>,
711        context: &mut WriteContext,
712        ref_mode: RefMode,
713        type_info: &Rc<TypeInfo>,
714    ) -> Result<(), Error> {
715        write_arc_weak_with_type_info::<T, C>(value, context, ref_mode, type_info)
716    }
717
718    #[inline(always)]
719    fn read(
720        context: &mut ReadContext,
721        ref_mode: RefMode,
722        read_type_info: bool,
723    ) -> Result<ArcWeak<T>, Error> {
724        read_arc_weak::<T, C>(context, ref_mode, read_type_info, None)
725    }
726
727    #[inline(always)]
728    fn read_with_type_info(
729        context: &mut ReadContext,
730        ref_mode: RefMode,
731        type_info: &Rc<TypeInfo>,
732    ) -> Result<ArcWeak<T>, Error> {
733        read_arc_weak::<T, C>(context, ref_mode, false, Some(type_info))
734    }
735
736    #[inline(always)]
737    fn default_value(context: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
738        reserve_weak_cell::<std::sync::Weak<T>>(context)?;
739        Ok(ArcWeak::new())
740    }
741
742    #[inline(always)]
743    fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
744        C::write_type_info(context)
745    }
746
747    #[inline(always)]
748    fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
749        C::read_type_info(context)
750    }
751
752    #[inline(always)]
753    fn static_type_id() -> TypeId {
754        C::static_type_id()
755    }
756
757    #[inline(always)]
758    fn metadata_target_type_id() -> std::any::TypeId {
759        C::metadata_target_type_id()
760    }
761
762    const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
763
764    const IS_SHARED_REF: bool = true;
765
766    const IS_WRAPPER: bool = true;
767
768    const REQUIRES_SCOPED_ACCESS: bool = true;
769
770    #[inline(always)]
771    fn dynamic_type_id(value: &ArcWeak<T>) -> Result<Option<std::any::TypeId>, Error> {
772        match value.upgrade() {
773            Some(value) => C::dynamic_type_id(&value),
774            None => Ok(None),
775        }
776    }
777}
778
779impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<ArcWeak<T>>
780    for ArcWeakCodec<T, C, NULLABLE, TRACK_REF>
781where
782    T: Send + Sync + 'static,
783    C: Codec<T>,
784{
785    #[inline(always)]
786    fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
787        let mut field_type = C::field_type(type_resolver)?;
788        field_type.nullable = NULLABLE;
789        field_type.track_ref = true;
790        Ok(field_type)
791    }
792
793    #[inline(always)]
794    fn write_field(value: &ArcWeak<T>, context: &mut WriteContext) -> Result<(), Error> {
795        Self::write_with_mode(
796            value,
797            context,
798            RefMode::Tracking,
799            super::codec::codec_write_type_info::<T, C>(context),
800            true,
801        )
802    }
803
804    #[inline(always)]
805    fn read_field(context: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
806        <Self as Serializer>::read(
807            context,
808            RefMode::Tracking,
809            codec_read_type_info_static::<T, C>(context),
810        )
811    }
812
813    #[inline(always)]
814    fn read_field_with_type(
815        context: &mut ReadContext,
816        remote_field_type: &FieldType,
817    ) -> Result<ArcWeak<T>, Error> {
818        read_arc_weak_with_type::<T, C>(context, RefMode::Tracking, remote_field_type)
819    }
820
821    #[inline(always)]
822    fn write_with_mode(
823        value: &ArcWeak<T>,
824        context: &mut WriteContext,
825        ref_mode: RefMode,
826        write_type_info: bool,
827        has_generics: bool,
828    ) -> Result<(), Error> {
829        write_arc_weak_field::<T, C>(value, context, ref_mode, write_type_info, has_generics)
830    }
831
832    #[inline(always)]
833    fn write_with_type_info(
834        value: &ArcWeak<T>,
835        context: &mut WriteContext,
836        ref_mode: RefMode,
837        type_info: &Rc<TypeInfo>,
838        has_generics: bool,
839    ) -> Result<(), Error> {
840        write_arc_weak_field_with_type_info::<T, C>(
841            value,
842            context,
843            ref_mode,
844            type_info,
845            has_generics,
846        )
847    }
848
849    #[inline(always)]
850    fn read_type_info_value(
851        context: &mut ReadContext,
852    ) -> Result<super::codec::CodecReadType, Error> {
853        C::read_type_info_value(context)
854    }
855}
856
857impl_single_carrier_serializer!(RcWeakSerializer, RcWeak, RcWeakCodec, wrapper = true);
858
859impl_single_carrier_serializer!(
860    ArcWeakSerializer,
861    ArcWeak,
862    ArcWeakCodec,
863    wrapper = true,
864    bounds = [Send + Sync]
865);