Skip to main content

fory_core/serializer/
arc.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use super::codec::{
19    codec_read_type_info, codec_read_type_info_static, codec_ref_mode, codec_write_type_info,
20    field_ref_mode, Codec,
21};
22use crate::context::{ReadContext, WriteContext};
23use crate::error::Error;
24use crate::meta::FieldType;
25use crate::resolver::{RefFlag, RefMode, TypeInfo, TypeResolver};
26use crate::serializer::Serializer;
27use crate::type_id::TypeId;
28use std::marker::PhantomData;
29use std::rc::Rc;
30use std::sync::Arc;
31
32pub struct ArcCodec<T, C, const NULLABLE: bool, const TRACK_REF: bool>(PhantomData<(T, C)>);
33
34#[cold]
35#[inline(never)]
36fn shared_arc_child() -> Error {
37    Error::not_allowed("Arc<T> where T is a shared ref type is not allowed")
38}
39
40#[cold]
41#[inline(never)]
42fn missing_arc_ref(ref_id: u32) -> Error {
43    Error::invalid_ref(format!("Arc reference {ref_id} not found"))
44}
45
46#[inline(always)]
47fn check_child<T: 'static, C: Serializer<Target = T>>() -> Result<(), Error> {
48    // Nested shared owners would compete for reference framing and identity
49    // while both wrappers remain transparent on the wire.
50    if C::IS_SHARED_REF {
51        Err(shared_arc_child())
52    } else {
53        Ok(())
54    }
55}
56
57#[inline(always)]
58fn reserve_arc<T>(context: &mut ReadContext) -> Result<(), Error> {
59    let bytes = std::mem::size_of::<T>();
60    if bytes != 0 {
61        context.reserve_graph_memory(bytes)?;
62    }
63    Ok(())
64}
65
66#[inline(always)]
67fn write_inner<T: 'static, C: Serializer<Target = T>>(
68    value: &T,
69    context: &mut WriteContext,
70    write_type_info: bool,
71) -> Result<(), Error> {
72    check_child::<T, C>()?;
73    C::write(value, context, RefMode::None, write_type_info)
74}
75
76#[inline(always)]
77fn write_inner_with_type_info<T: 'static, C: Serializer<Target = T>>(
78    value: &T,
79    context: &mut WriteContext,
80    type_info: &Rc<TypeInfo>,
81) -> Result<(), Error> {
82    check_child::<T, C>()?;
83    C::write_with_type_info(value, context, RefMode::None, type_info)
84}
85
86#[inline(always)]
87fn write_inner_field<T: 'static, C: Codec<T>>(
88    value: &T,
89    context: &mut WriteContext,
90    write_type_info: bool,
91    has_generics: bool,
92) -> Result<(), Error> {
93    check_child::<T, C>()?;
94    C::write_with_mode(value, context, RefMode::None, write_type_info, has_generics)
95}
96
97#[inline(always)]
98fn write_inner_field_with_type_info<T: 'static, C: Codec<T>>(
99    value: &T,
100    context: &mut WriteContext,
101    type_info: &Rc<TypeInfo>,
102    has_generics: bool,
103) -> Result<(), Error> {
104    check_child::<T, C>()?;
105    <C as Codec<T>>::write_with_type_info(value, context, RefMode::None, type_info, has_generics)
106}
107
108#[inline(always)]
109fn write_ref<T>(value: &Arc<T>, context: &mut WriteContext, ref_mode: RefMode) -> bool {
110    match ref_mode {
111        RefMode::None => true,
112        RefMode::NullOnly => {
113            context.writer.write_i8(RefFlag::NotNullValue as i8);
114            true
115        }
116        RefMode::Tracking => !context
117            .ref_writer
118            .try_write_arc_ref(&mut context.writer, value),
119    }
120}
121
122#[inline(always)]
123fn read_inner<T: 'static, C: Serializer<Target = T>>(
124    context: &mut ReadContext,
125    read_type_info: bool,
126    type_info: Option<&Rc<TypeInfo>>,
127) -> Result<T, Error> {
128    check_child::<T, C>()?;
129    reserve_arc::<T>(context)?;
130    if let Some(type_info) = type_info {
131        return C::read_with_type_info(context, RefMode::None, type_info);
132    }
133    if read_type_info {
134        C::read_type_info(context)?;
135    }
136    C::read_data(context)
137}
138
139#[inline(always)]
140fn read_inner_with_type<T: 'static, C: Codec<T>>(
141    context: &mut ReadContext,
142    remote_field_type: &FieldType,
143) -> Result<T, Error> {
144    check_child::<T, C>()?;
145    reserve_arc::<T>(context)?;
146    // The Arc envelope owns only reference framing. A compatible
147    // metadata-bearing child still owns its inline TypeInfo before its body,
148    // while declared carrier children consume the remote schema directly.
149    if codec_read_type_info::<T, C>(context, remote_field_type) {
150        return C::read(context, RefMode::None, true);
151    }
152    C::read_data_with_type(context, remote_field_type)
153}
154
155impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
156    for ArcCodec<T, C, NULLABLE, TRACK_REF>
157where
158    T: Send + Sync + 'static,
159    C: Serializer<Target = T>,
160{
161    type Target = Arc<T>;
162
163    #[inline(always)]
164    fn reserved_space() -> usize {
165        4
166    }
167
168    #[inline(always)]
169    fn write_data(value: &Arc<T>, context: &mut WriteContext) -> Result<(), Error> {
170        write_inner::<T, C>(value, context, false)
171    }
172
173    #[inline(always)]
174    fn read_data(context: &mut ReadContext) -> Result<Arc<T>, Error> {
175        Ok(Arc::new(read_inner::<T, C>(context, false, None)?))
176    }
177
178    #[inline(always)]
179    fn write(
180        value: &Arc<T>,
181        context: &mut WriteContext,
182        ref_mode: RefMode,
183        write_type_info: bool,
184    ) -> Result<(), Error> {
185        if !write_ref(value, context, ref_mode) {
186            return Ok(());
187        }
188        write_inner::<T, C>(value, context, write_type_info)
189    }
190
191    #[inline(always)]
192    fn write_type_info_value(
193        context: &mut WriteContext,
194        target_type_id: std::any::TypeId,
195    ) -> Result<Rc<TypeInfo>, Error> {
196        C::write_type_info_value(context, target_type_id)
197    }
198
199    #[inline(always)]
200    fn write_with_type_info(
201        value: &Arc<T>,
202        context: &mut WriteContext,
203        ref_mode: RefMode,
204        type_info: &Rc<TypeInfo>,
205    ) -> Result<(), Error> {
206        if !write_ref(value, context, ref_mode) {
207            return Ok(());
208        }
209        write_inner_with_type_info::<T, C>(value, context, type_info)
210    }
211
212    #[inline(always)]
213    fn read(
214        context: &mut ReadContext,
215        ref_mode: RefMode,
216        read_type_info: bool,
217    ) -> Result<Arc<T>, Error> {
218        read_arc::<T, C>(context, ref_mode, read_type_info, None)
219    }
220
221    #[inline(always)]
222    fn read_with_type_info(
223        context: &mut ReadContext,
224        ref_mode: RefMode,
225        type_info: &Rc<TypeInfo>,
226    ) -> Result<Arc<T>, Error> {
227        read_arc::<T, C>(context, ref_mode, false, Some(type_info))
228    }
229
230    #[inline(always)]
231    fn default_value(context: &mut ReadContext) -> Result<Arc<T>, Error> {
232        check_child::<T, C>()?;
233        reserve_arc::<T>(context)?;
234        Ok(Arc::new(C::default_value(context)?))
235    }
236
237    #[inline(always)]
238    fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
239        C::write_type_info(context)
240    }
241
242    #[inline(always)]
243    fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
244        C::read_type_info(context)
245    }
246
247    #[inline(always)]
248    fn static_type_id() -> TypeId {
249        C::static_type_id()
250    }
251
252    const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
253
254    const IS_SHARED_REF: bool = true;
255
256    const IS_WRAPPER: bool = true;
257
258    const REQUIRES_SCOPED_ACCESS: bool = C::REQUIRES_SCOPED_ACCESS;
259
260    #[inline(always)]
261    fn dynamic_type_id(value: &Arc<T>) -> Result<Option<std::any::TypeId>, Error> {
262        C::dynamic_type_id(value)
263    }
264}
265
266impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<Arc<T>>
267    for ArcCodec<T, C, NULLABLE, TRACK_REF>
268where
269    T: Send + Sync + 'static,
270    C: Codec<T>,
271{
272    #[inline(always)]
273    fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
274        let mut field_type = C::field_type(type_resolver)?;
275        field_type.nullable = NULLABLE;
276        field_type.track_ref = TRACK_REF;
277        Ok(field_type)
278    }
279
280    #[inline(always)]
281    fn write_field(value: &Arc<T>, context: &mut WriteContext) -> Result<(), Error> {
282        Self::write_with_mode(
283            value,
284            context,
285            codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
286            codec_write_type_info::<T, C>(context),
287            true,
288        )
289    }
290
291    #[inline(always)]
292    fn read_field(context: &mut ReadContext) -> Result<Arc<T>, Error> {
293        <Self as Serializer>::read(
294            context,
295            codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
296            codec_read_type_info_static::<T, C>(context),
297        )
298    }
299
300    #[inline(always)]
301    fn read_data_with_type(
302        context: &mut ReadContext,
303        remote_data_type: &FieldType,
304    ) -> Result<Arc<T>, Error> {
305        check_child::<T, C>()?;
306        reserve_arc::<T>(context)?;
307        Ok(Arc::new(C::read_data_with_type(context, remote_data_type)?))
308    }
309
310    #[inline(always)]
311    fn read_field_with_type(
312        context: &mut ReadContext,
313        remote_field_type: &FieldType,
314    ) -> Result<Arc<T>, Error> {
315        read_arc_with_type::<T, C>(
316            context,
317            field_ref_mode(remote_field_type),
318            remote_field_type,
319        )
320    }
321
322    #[inline(always)]
323    fn write_with_mode(
324        value: &Arc<T>,
325        context: &mut WriteContext,
326        ref_mode: RefMode,
327        write_type_info: bool,
328        has_generics: bool,
329    ) -> Result<(), Error> {
330        if !write_ref(value, context, ref_mode) {
331            return Ok(());
332        }
333        write_inner_field::<T, C>(value, context, write_type_info, has_generics)
334    }
335
336    #[inline(always)]
337    fn write_with_type_info(
338        value: &Arc<T>,
339        context: &mut WriteContext,
340        ref_mode: RefMode,
341        type_info: &Rc<TypeInfo>,
342        has_generics: bool,
343    ) -> Result<(), Error> {
344        if !write_ref(value, context, ref_mode) {
345            return Ok(());
346        }
347        write_inner_field_with_type_info::<T, C>(value, context, type_info, has_generics)
348    }
349
350    #[inline(always)]
351    fn read_type_info_value(
352        context: &mut ReadContext,
353    ) -> Result<super::codec::CodecReadType, Error> {
354        C::read_type_info_value(context)
355    }
356}
357
358macro_rules! read_arc_owner {
359    ($context:ident, $ref_mode:expr, $read_inner:expr, $default:expr) => {
360        match $ref_mode {
361            RefMode::None => Ok(Arc::new($read_inner?)),
362            RefMode::NullOnly => {
363                if $context.reader.read_i8()? == RefFlag::Null as i8 {
364                    return $default;
365                }
366                Ok(Arc::new($read_inner?))
367            }
368            RefMode::Tracking => match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
369                RefFlag::Null => $default,
370                RefFlag::Ref => {
371                    let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
372                    $context
373                        .ref_reader
374                        .get_arc_ref::<T>(ref_id)
375                        .ok_or_else(|| missing_arc_ref(ref_id))
376                }
377                RefFlag::NotNullValue => Ok(Arc::new($read_inner?)),
378                RefFlag::RefValue => {
379                    let ref_id = $context.ref_reader.reserve_ref_id();
380                    let value = Arc::new($read_inner?);
381                    $context.ref_reader.store_arc_ref_at(ref_id, value.clone());
382                    Ok(value)
383                }
384            },
385        }
386    };
387}
388
389#[inline(always)]
390fn read_arc<T: Send + Sync + 'static, C: Serializer<Target = T>>(
391    context: &mut ReadContext,
392    ref_mode: RefMode,
393    read_type_info: bool,
394    type_info: Option<&Rc<TypeInfo>>,
395) -> Result<Arc<T>, Error> {
396    read_arc_owner!(
397        context,
398        ref_mode,
399        read_inner::<T, C>(context, read_type_info, type_info),
400        <ArcCodec<T, C, false, false> as Serializer>::default_value(context)
401    )
402}
403
404#[inline(always)]
405fn read_arc_with_type<T: Send + Sync + 'static, C: Codec<T>>(
406    context: &mut ReadContext,
407    ref_mode: RefMode,
408    remote_field_type: &FieldType,
409) -> Result<Arc<T>, Error> {
410    read_arc_owner!(
411        context,
412        ref_mode,
413        read_inner_with_type::<T, C>(context, remote_field_type),
414        <ArcCodec<T, C, false, false> as Serializer>::default_value(context)
415    )
416}
417
418impl_single_carrier_serializer!(
419    ArcSerializer,
420    Arc,
421    ArcCodec,
422    wrapper = true,
423    bounds = [Send + Sync]
424);