1use 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 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 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 #[inline(always)]
253 fn metadata_target_type_id() -> std::any::TypeId {
254 C::metadata_target_type_id()
255 }
256
257 const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
258
259 const IS_SHARED_REF: bool = true;
260
261 const IS_WRAPPER: bool = true;
262
263 const REQUIRES_SCOPED_ACCESS: bool = C::REQUIRES_SCOPED_ACCESS;
264
265 #[inline(always)]
266 fn dynamic_type_id(value: &Arc<T>) -> Result<Option<std::any::TypeId>, Error> {
267 C::dynamic_type_id(value)
268 }
269}
270
271impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<Arc<T>>
272 for ArcCodec<T, C, NULLABLE, TRACK_REF>
273where
274 T: Send + Sync + 'static,
275 C: Codec<T>,
276{
277 #[inline(always)]
278 fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
279 let mut field_type = C::field_type(type_resolver)?;
280 field_type.nullable = NULLABLE;
281 field_type.track_ref = TRACK_REF;
282 Ok(field_type)
283 }
284
285 #[inline(always)]
286 fn write_field(value: &Arc<T>, context: &mut WriteContext) -> Result<(), Error> {
287 Self::write_with_mode(
288 value,
289 context,
290 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
291 codec_write_type_info::<T, C>(context),
292 true,
293 )
294 }
295
296 #[inline(always)]
297 fn read_field(context: &mut ReadContext) -> Result<Arc<T>, Error> {
298 <Self as Serializer>::read(
299 context,
300 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
301 codec_read_type_info_static::<T, C>(context),
302 )
303 }
304
305 #[inline(always)]
306 fn read_data_with_type(
307 context: &mut ReadContext,
308 remote_data_type: &FieldType,
309 ) -> Result<Arc<T>, Error> {
310 check_child::<T, C>()?;
311 reserve_arc::<T>(context)?;
312 Ok(Arc::new(C::read_data_with_type(context, remote_data_type)?))
313 }
314
315 #[inline(always)]
316 fn read_field_with_type(
317 context: &mut ReadContext,
318 remote_field_type: &FieldType,
319 ) -> Result<Arc<T>, Error> {
320 read_arc_with_type::<T, C>(
321 context,
322 field_ref_mode(remote_field_type),
323 remote_field_type,
324 )
325 }
326
327 #[inline(always)]
328 fn write_with_mode(
329 value: &Arc<T>,
330 context: &mut WriteContext,
331 ref_mode: RefMode,
332 write_type_info: bool,
333 has_generics: bool,
334 ) -> Result<(), Error> {
335 if !write_ref(value, context, ref_mode) {
336 return Ok(());
337 }
338 write_inner_field::<T, C>(value, context, write_type_info, has_generics)
339 }
340
341 #[inline(always)]
342 fn write_with_type_info(
343 value: &Arc<T>,
344 context: &mut WriteContext,
345 ref_mode: RefMode,
346 type_info: &Rc<TypeInfo>,
347 has_generics: bool,
348 ) -> Result<(), Error> {
349 if !write_ref(value, context, ref_mode) {
350 return Ok(());
351 }
352 write_inner_field_with_type_info::<T, C>(value, context, type_info, has_generics)
353 }
354
355 #[inline(always)]
356 fn read_type_info_value(
357 context: &mut ReadContext,
358 ) -> Result<super::codec::CodecReadType, Error> {
359 C::read_type_info_value(context)
360 }
361}
362
363macro_rules! read_arc_owner {
364 ($context:ident, $ref_mode:expr, $read_inner:expr, $default:expr) => {
365 match $ref_mode {
366 RefMode::None => Ok(Arc::new($read_inner?)),
367 RefMode::NullOnly => {
368 if $context.reader.read_i8()? == RefFlag::Null as i8 {
369 return $default;
370 }
371 Ok(Arc::new($read_inner?))
372 }
373 RefMode::Tracking => match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
374 RefFlag::Null => $default,
375 RefFlag::Ref => {
376 let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
377 $context
378 .ref_reader
379 .get_arc_ref::<T>(ref_id)
380 .ok_or_else(|| missing_arc_ref(ref_id))
381 }
382 RefFlag::NotNullValue => Ok(Arc::new($read_inner?)),
383 RefFlag::RefValue => {
384 let ref_id = $context.ref_reader.reserve_ref_id();
385 let value = Arc::new($read_inner?);
386 $context.ref_reader.store_arc_ref_at(ref_id, value.clone());
387 Ok(value)
388 }
389 },
390 }
391 };
392}
393
394#[inline(always)]
395fn read_arc<T: Send + Sync + 'static, C: Serializer<Target = T>>(
396 context: &mut ReadContext,
397 ref_mode: RefMode,
398 read_type_info: bool,
399 type_info: Option<&Rc<TypeInfo>>,
400) -> Result<Arc<T>, Error> {
401 read_arc_owner!(
402 context,
403 ref_mode,
404 read_inner::<T, C>(context, read_type_info, type_info),
405 <ArcCodec<T, C, false, false> as Serializer>::default_value(context)
406 )
407}
408
409#[inline(always)]
410fn read_arc_with_type<T: Send + Sync + 'static, C: Codec<T>>(
411 context: &mut ReadContext,
412 ref_mode: RefMode,
413 remote_field_type: &FieldType,
414) -> Result<Arc<T>, Error> {
415 read_arc_owner!(
416 context,
417 ref_mode,
418 read_inner_with_type::<T, C>(context, remote_field_type),
419 <ArcCodec<T, C, false, false> as Serializer>::default_value(context)
420 )
421}
422
423impl_single_carrier_serializer!(
424 ArcSerializer,
425 Arc,
426 ArcCodec,
427 wrapper = true,
428 bounds = [Send + Sync]
429);