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 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);