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    const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
376
377    const IS_SHARED_REF: bool = true;
378
379    const IS_WRAPPER: bool = true;
380
381    const REQUIRES_SCOPED_ACCESS: bool = true;
382
383    #[inline(always)]
384    fn dynamic_type_id(value: &RcWeak<T>) -> Result<Option<std::any::TypeId>, Error> {
385        match value.upgrade() {
386            Some(value) => C::dynamic_type_id(&value),
387            None => Ok(None),
388        }
389    }
390}
391
392impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<RcWeak<T>>
393    for RcWeakCodec<T, C, NULLABLE, TRACK_REF>
394where
395    T: 'static,
396    C: Codec<T>,
397{
398    #[inline(always)]
399    fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
400        let mut field_type = C::field_type(type_resolver)?;
401        field_type.nullable = NULLABLE;
402        field_type.track_ref = true;
403        Ok(field_type)
404    }
405
406    #[inline(always)]
407    fn write_field(value: &RcWeak<T>, context: &mut WriteContext) -> Result<(), Error> {
408        Self::write_with_mode(
409            value,
410            context,
411            RefMode::Tracking,
412            super::codec::codec_write_type_info::<T, C>(context),
413            true,
414        )
415    }
416
417    #[inline(always)]
418    fn read_field(context: &mut ReadContext) -> Result<RcWeak<T>, Error> {
419        <Self as Serializer>::read(
420            context,
421            RefMode::Tracking,
422            codec_read_type_info_static::<T, C>(context),
423        )
424    }
425
426    #[inline(always)]
427    fn read_field_with_type(
428        context: &mut ReadContext,
429        remote_field_type: &FieldType,
430    ) -> Result<RcWeak<T>, Error> {
431        read_rc_weak_with_type::<T, C>(context, RefMode::Tracking, remote_field_type)
432    }
433
434    #[inline(always)]
435    fn write_with_mode(
436        value: &RcWeak<T>,
437        context: &mut WriteContext,
438        ref_mode: RefMode,
439        write_type_info: bool,
440        has_generics: bool,
441    ) -> Result<(), Error> {
442        write_rc_weak_field::<T, C>(value, context, ref_mode, write_type_info, has_generics)
443    }
444
445    #[inline(always)]
446    fn write_with_type_info(
447        value: &RcWeak<T>,
448        context: &mut WriteContext,
449        ref_mode: RefMode,
450        type_info: &Rc<TypeInfo>,
451        has_generics: bool,
452    ) -> Result<(), Error> {
453        write_rc_weak_field_with_type_info::<T, C>(
454            value,
455            context,
456            ref_mode,
457            type_info,
458            has_generics,
459        )
460    }
461
462    #[inline(always)]
463    fn read_type_info_value(
464        context: &mut ReadContext,
465    ) -> Result<super::codec::CodecReadType, Error> {
466        C::read_type_info_value(context)
467    }
468}
469
470#[inline(always)]
471fn arc_weak_body<T: Send + Sync + 'static>(
472    value: &ArcWeak<T>,
473    context: &mut WriteContext,
474    ref_mode: RefMode,
475) -> Result<Option<Arc<T>>, Error> {
476    if !context.is_track_ref() {
477        return Err(arc_weak_tracking_error());
478    }
479    if ref_mode != RefMode::Tracking {
480        return Err(weak_write_mode_error("ArcWeak"));
481    }
482    let Some(value) = value.upgrade() else {
483        context.writer.write_i8(RefFlag::Null as i8);
484        return Ok(None);
485    };
486    if context
487        .ref_writer
488        .try_write_arc_ref(&mut context.writer, &value)
489    {
490        return Ok(None);
491    }
492    Ok(Some(value))
493}
494
495#[inline(always)]
496fn write_arc_weak<T: Send + Sync + 'static, C: Serializer<Target = T>>(
497    value: &ArcWeak<T>,
498    context: &mut WriteContext,
499    ref_mode: RefMode,
500    write_type_info: bool,
501) -> Result<(), Error> {
502    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
503        return Ok(());
504    };
505    C::write(&value, context, RefMode::None, write_type_info)
506}
507
508#[inline(always)]
509fn write_arc_weak_field<T: Send + Sync + 'static, C: Codec<T>>(
510    value: &ArcWeak<T>,
511    context: &mut WriteContext,
512    ref_mode: RefMode,
513    write_type_info: bool,
514    has_generics: bool,
515) -> Result<(), Error> {
516    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
517        return Ok(());
518    };
519    C::write_with_mode(
520        &value,
521        context,
522        RefMode::None,
523        write_type_info,
524        has_generics,
525    )
526}
527
528#[inline(always)]
529fn write_arc_weak_with_type_info<T: Send + Sync + 'static, C: Serializer<Target = T>>(
530    value: &ArcWeak<T>,
531    context: &mut WriteContext,
532    ref_mode: RefMode,
533    type_info: &Rc<TypeInfo>,
534) -> Result<(), Error> {
535    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
536        return Ok(());
537    };
538    C::write_with_type_info(&value, context, RefMode::None, type_info)
539}
540
541#[inline(always)]
542fn write_arc_weak_field_with_type_info<T: Send + Sync + 'static, C: Codec<T>>(
543    value: &ArcWeak<T>,
544    context: &mut WriteContext,
545    ref_mode: RefMode,
546    type_info: &Rc<TypeInfo>,
547    has_generics: bool,
548) -> Result<(), Error> {
549    let Some(value) = arc_weak_body(value, context, ref_mode)? else {
550        return Ok(());
551    };
552    <C as Codec<T>>::write_with_type_info(&value, context, RefMode::None, type_info, has_generics)
553}
554
555#[inline(always)]
556fn read_arc_inner<T: Send + Sync + 'static, C: Serializer<Target = T>>(
557    context: &mut ReadContext,
558    read_type_info: bool,
559    type_info: Option<&Rc<TypeInfo>>,
560) -> Result<T, Error> {
561    reserve_strong::<T>(context)?;
562    if let Some(type_info) = type_info {
563        return C::read_with_type_info(context, RefMode::None, type_info);
564    }
565    // The weak envelope has consumed its ref flag; the child still owns any
566    // inline dynamic metadata before its body.
567    C::read(context, RefMode::None, read_type_info)
568}
569
570#[inline(always)]
571fn read_arc_inner_with_type<T: Send + Sync + 'static, C: Codec<T>>(
572    context: &mut ReadContext,
573    remote_field_type: &FieldType,
574) -> Result<T, Error> {
575    reserve_strong::<T>(context)?;
576    // The weak envelope owns only reference framing. A compatible
577    // metadata-bearing child still owns its inline TypeInfo before its body,
578    // while declared carrier children consume the remote schema directly.
579    if codec_read_type_info::<T, C>(context, remote_field_type) {
580        return C::read(context, RefMode::None, true);
581    }
582    C::read_data_with_type(context, remote_field_type)
583}
584
585macro_rules! read_arc_weak_owner {
586    ($context:ident, $ref_mode:expr, $read_inner:expr) => {{
587        if $ref_mode != RefMode::Tracking {
588            return Err(weak_read_mode_error("ArcWeak"));
589        }
590        match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
591            RefFlag::Null => {
592                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
593                Ok(ArcWeak::new())
594            }
595            RefFlag::RefValue => {
596                // The writer assigns the strong target's ID before its body.
597                // Reserve that slot now, but publish only the final Arc after
598                // the complete child read succeeds.
599                let ref_id = $context.ref_reader.reserve_ref_id();
600                $context.inc_depth()?;
601                let value = $read_inner?;
602                $context.dec_depth();
603                let strong = Arc::new(value);
604                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
605                $context.ref_reader.store_arc_ref_at(ref_id, strong.clone());
606                Ok(ArcWeak::from(&strong))
607            }
608            RefFlag::Ref => {
609                let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
610                reserve_weak_cell::<std::sync::Weak<T>>($context)?;
611                let weak = ArcWeak::new();
612                if let Some(strong) = $context.ref_reader.get_arc_ref::<T>(ref_id) {
613                    weak.update(Arc::downgrade(&strong));
614                } else {
615                    let callback_weak = weak.clone();
616                    $context.ref_reader.add_callback(Box::new(move |reader| {
617                        if let Some(strong) = reader.get_arc_ref::<T>(ref_id) {
618                            callback_weak.update(Arc::downgrade(&strong));
619                        }
620                    }));
621                }
622                Ok(weak)
623            }
624            RefFlag::NotNullValue => Err(weak_untracked_value("ArcWeak")),
625        }
626    }};
627}
628
629#[inline(always)]
630fn read_arc_weak<T: Send + Sync + 'static, C: Serializer<Target = T>>(
631    context: &mut ReadContext,
632    ref_mode: RefMode,
633    read_type_info: bool,
634    type_info: Option<&Rc<TypeInfo>>,
635) -> Result<ArcWeak<T>, Error> {
636    read_arc_weak_owner!(
637        context,
638        ref_mode,
639        read_arc_inner::<T, C>(context, read_type_info, type_info)
640    )
641}
642
643#[inline(always)]
644fn read_arc_weak_with_type<T: Send + Sync + 'static, C: Codec<T>>(
645    context: &mut ReadContext,
646    ref_mode: RefMode,
647    remote_field_type: &FieldType,
648) -> Result<ArcWeak<T>, Error> {
649    read_arc_weak_owner!(
650        context,
651        ref_mode,
652        read_arc_inner_with_type::<T, C>(context, remote_field_type)
653    )
654}
655
656impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
657    for ArcWeakCodec<T, C, NULLABLE, TRACK_REF>
658where
659    T: Send + Sync + 'static,
660    C: Serializer<Target = T>,
661{
662    type Target = ArcWeak<T>;
663
664    #[inline(always)]
665    fn reserved_space() -> usize {
666        4
667    }
668
669    #[cold]
670    #[inline(never)]
671    fn write_data(_: &ArcWeak<T>, _: &mut WriteContext) -> Result<(), Error> {
672        Err(Error::not_allowed(
673            "ArcWeak must be written through its reference-tracking envelope",
674        ))
675    }
676
677    #[cold]
678    #[inline(never)]
679    fn read_data(_: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
680        Err(Error::not_allowed(
681            "ArcWeak must be read through its reference-tracking envelope",
682        ))
683    }
684
685    #[inline(always)]
686    fn write(
687        value: &ArcWeak<T>,
688        context: &mut WriteContext,
689        ref_mode: RefMode,
690        write_type_info: bool,
691    ) -> Result<(), Error> {
692        write_arc_weak::<T, C>(value, context, ref_mode, write_type_info)
693    }
694
695    #[inline(always)]
696    fn write_type_info_value(
697        context: &mut WriteContext,
698        target_type_id: std::any::TypeId,
699    ) -> Result<Rc<TypeInfo>, Error> {
700        C::write_type_info_value(context, target_type_id)
701    }
702
703    #[inline(always)]
704    fn write_with_type_info(
705        value: &ArcWeak<T>,
706        context: &mut WriteContext,
707        ref_mode: RefMode,
708        type_info: &Rc<TypeInfo>,
709    ) -> Result<(), Error> {
710        write_arc_weak_with_type_info::<T, C>(value, context, ref_mode, type_info)
711    }
712
713    #[inline(always)]
714    fn read(
715        context: &mut ReadContext,
716        ref_mode: RefMode,
717        read_type_info: bool,
718    ) -> Result<ArcWeak<T>, Error> {
719        read_arc_weak::<T, C>(context, ref_mode, read_type_info, None)
720    }
721
722    #[inline(always)]
723    fn read_with_type_info(
724        context: &mut ReadContext,
725        ref_mode: RefMode,
726        type_info: &Rc<TypeInfo>,
727    ) -> Result<ArcWeak<T>, Error> {
728        read_arc_weak::<T, C>(context, ref_mode, false, Some(type_info))
729    }
730
731    #[inline(always)]
732    fn default_value(context: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
733        reserve_weak_cell::<std::sync::Weak<T>>(context)?;
734        Ok(ArcWeak::new())
735    }
736
737    #[inline(always)]
738    fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
739        C::write_type_info(context)
740    }
741
742    #[inline(always)]
743    fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
744        C::read_type_info(context)
745    }
746
747    #[inline(always)]
748    fn static_type_id() -> TypeId {
749        C::static_type_id()
750    }
751
752    const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
753
754    const IS_SHARED_REF: bool = true;
755
756    const IS_WRAPPER: bool = true;
757
758    const REQUIRES_SCOPED_ACCESS: bool = true;
759
760    #[inline(always)]
761    fn dynamic_type_id(value: &ArcWeak<T>) -> Result<Option<std::any::TypeId>, Error> {
762        match value.upgrade() {
763            Some(value) => C::dynamic_type_id(&value),
764            None => Ok(None),
765        }
766    }
767}
768
769impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<ArcWeak<T>>
770    for ArcWeakCodec<T, C, NULLABLE, TRACK_REF>
771where
772    T: Send + Sync + 'static,
773    C: Codec<T>,
774{
775    #[inline(always)]
776    fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
777        let mut field_type = C::field_type(type_resolver)?;
778        field_type.nullable = NULLABLE;
779        field_type.track_ref = true;
780        Ok(field_type)
781    }
782
783    #[inline(always)]
784    fn write_field(value: &ArcWeak<T>, context: &mut WriteContext) -> Result<(), Error> {
785        Self::write_with_mode(
786            value,
787            context,
788            RefMode::Tracking,
789            super::codec::codec_write_type_info::<T, C>(context),
790            true,
791        )
792    }
793
794    #[inline(always)]
795    fn read_field(context: &mut ReadContext) -> Result<ArcWeak<T>, Error> {
796        <Self as Serializer>::read(
797            context,
798            RefMode::Tracking,
799            codec_read_type_info_static::<T, C>(context),
800        )
801    }
802
803    #[inline(always)]
804    fn read_field_with_type(
805        context: &mut ReadContext,
806        remote_field_type: &FieldType,
807    ) -> Result<ArcWeak<T>, Error> {
808        read_arc_weak_with_type::<T, C>(context, RefMode::Tracking, remote_field_type)
809    }
810
811    #[inline(always)]
812    fn write_with_mode(
813        value: &ArcWeak<T>,
814        context: &mut WriteContext,
815        ref_mode: RefMode,
816        write_type_info: bool,
817        has_generics: bool,
818    ) -> Result<(), Error> {
819        write_arc_weak_field::<T, C>(value, context, ref_mode, write_type_info, has_generics)
820    }
821
822    #[inline(always)]
823    fn write_with_type_info(
824        value: &ArcWeak<T>,
825        context: &mut WriteContext,
826        ref_mode: RefMode,
827        type_info: &Rc<TypeInfo>,
828        has_generics: bool,
829    ) -> Result<(), Error> {
830        write_arc_weak_field_with_type_info::<T, C>(
831            value,
832            context,
833            ref_mode,
834            type_info,
835            has_generics,
836        )
837    }
838
839    #[inline(always)]
840    fn read_type_info_value(
841        context: &mut ReadContext,
842    ) -> Result<super::codec::CodecReadType, Error> {
843        C::read_type_info_value(context)
844    }
845}
846
847impl_single_carrier_serializer!(RcWeakSerializer, RcWeak, RcWeakCodec, wrapper = true);
848
849impl_single_carrier_serializer!(
850    ArcWeakSerializer,
851    ArcWeak,
852    ArcWeakCodec,
853    wrapper = true,
854    bounds = [Send + Sync]
855);