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