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;
30
31pub struct RcCodec<T, C, const NULLABLE: bool, const TRACK_REF: bool>(PhantomData<(T, C)>);
32
33#[cold]
34#[inline(never)]
35fn shared_rc_child() -> Error {
36 Error::not_allowed("Rc<T> where T is a shared ref type is not allowed")
37}
38
39#[cold]
40#[inline(never)]
41fn missing_rc_ref(ref_id: u32) -> Error {
42 Error::invalid_ref(format!("Rc reference {ref_id} not found"))
43}
44
45#[inline(always)]
46fn check_child<T: 'static, C: Serializer<Target = T>>() -> Result<(), Error> {
47 if C::IS_SHARED_REF {
50 Err(shared_rc_child())
51 } else {
52 Ok(())
53 }
54}
55
56#[inline(always)]
57fn reserve_rc<T>(context: &mut ReadContext) -> Result<(), Error> {
58 let bytes = std::mem::size_of::<T>();
59 if bytes != 0 {
60 context.reserve_graph_memory(bytes)?;
61 }
62 Ok(())
63}
64
65#[inline(always)]
66fn write_inner<T: 'static, C: Serializer<Target = T>>(
67 value: &T,
68 context: &mut WriteContext,
69 write_type_info: bool,
70) -> Result<(), Error> {
71 check_child::<T, C>()?;
72 C::write(value, context, RefMode::None, write_type_info)
73}
74
75#[inline(always)]
76fn write_inner_with_type_info<T: 'static, C: Serializer<Target = T>>(
77 value: &T,
78 context: &mut WriteContext,
79 type_info: &Rc<TypeInfo>,
80) -> Result<(), Error> {
81 check_child::<T, C>()?;
82 C::write_with_type_info(value, context, RefMode::None, type_info)
83}
84
85#[inline(always)]
86fn write_inner_field<T: 'static, C: Codec<T>>(
87 value: &T,
88 context: &mut WriteContext,
89 write_type_info: bool,
90 has_generics: bool,
91) -> Result<(), Error> {
92 check_child::<T, C>()?;
93 C::write_with_mode(value, context, RefMode::None, write_type_info, has_generics)
94}
95
96#[inline(always)]
97fn write_inner_field_with_type_info<T: 'static, C: Codec<T>>(
98 value: &T,
99 context: &mut WriteContext,
100 type_info: &Rc<TypeInfo>,
101 has_generics: bool,
102) -> Result<(), Error> {
103 check_child::<T, C>()?;
104 <C as Codec<T>>::write_with_type_info(value, context, RefMode::None, type_info, has_generics)
105}
106
107#[inline(always)]
108fn write_ref<T>(value: &Rc<T>, context: &mut WriteContext, ref_mode: RefMode) -> bool {
109 match ref_mode {
110 RefMode::None => true,
111 RefMode::NullOnly => {
112 context.writer.write_i8(RefFlag::NotNullValue as i8);
113 true
114 }
115 RefMode::Tracking => !context
116 .ref_writer
117 .try_write_rc_ref(&mut context.writer, value),
118 }
119}
120
121#[inline(always)]
122fn read_inner<T: 'static, C: Serializer<Target = T>>(
123 context: &mut ReadContext,
124 read_type_info: bool,
125 type_info: Option<&Rc<TypeInfo>>,
126) -> Result<T, Error> {
127 check_child::<T, C>()?;
128 reserve_rc::<T>(context)?;
129 if let Some(type_info) = type_info {
130 return C::read_with_type_info(context, RefMode::None, type_info);
131 }
132 if read_type_info {
133 C::read_type_info(context)?;
134 }
135 C::read_data(context)
136}
137
138#[inline(always)]
139fn read_inner_with_type<T: 'static, C: Codec<T>>(
140 context: &mut ReadContext,
141 remote_field_type: &FieldType,
142) -> Result<T, Error> {
143 check_child::<T, C>()?;
144 reserve_rc::<T>(context)?;
145 if codec_read_type_info::<T, C>(context, remote_field_type) {
149 return C::read(context, RefMode::None, true);
150 }
151 C::read_data_with_type(context, remote_field_type)
152}
153
154impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
155 for RcCodec<T, C, NULLABLE, TRACK_REF>
156where
157 T: 'static,
158 C: Serializer<Target = T>,
159{
160 type Target = Rc<T>;
161
162 #[inline(always)]
163 fn reserved_space() -> usize {
164 4
165 }
166
167 #[inline(always)]
168 fn write_data(value: &Rc<T>, context: &mut WriteContext) -> Result<(), Error> {
169 write_inner::<T, C>(value, context, false)
170 }
171
172 #[inline(always)]
173 fn read_data(context: &mut ReadContext) -> Result<Rc<T>, Error> {
174 Ok(Rc::new(read_inner::<T, C>(context, false, None)?))
175 }
176
177 #[inline(always)]
178 fn write(
179 value: &Rc<T>,
180 context: &mut WriteContext,
181 ref_mode: RefMode,
182 write_type_info: bool,
183 ) -> Result<(), Error> {
184 if !write_ref(value, context, ref_mode) {
185 return Ok(());
186 }
187 write_inner::<T, C>(value, context, write_type_info)
188 }
189
190 #[inline(always)]
191 fn write_type_info_value(
192 context: &mut WriteContext,
193 target_type_id: std::any::TypeId,
194 ) -> Result<Rc<TypeInfo>, Error> {
195 C::write_type_info_value(context, target_type_id)
196 }
197
198 #[inline(always)]
199 fn write_with_type_info(
200 value: &Rc<T>,
201 context: &mut WriteContext,
202 ref_mode: RefMode,
203 type_info: &Rc<TypeInfo>,
204 ) -> Result<(), Error> {
205 if !write_ref(value, context, ref_mode) {
206 return Ok(());
207 }
208 write_inner_with_type_info::<T, C>(value, context, type_info)
209 }
210
211 #[inline(always)]
212 fn read(
213 context: &mut ReadContext,
214 ref_mode: RefMode,
215 read_type_info: bool,
216 ) -> Result<Rc<T>, Error> {
217 read_rc::<T, C>(context, ref_mode, read_type_info, None)
218 }
219
220 #[inline(always)]
221 fn read_with_type_info(
222 context: &mut ReadContext,
223 ref_mode: RefMode,
224 type_info: &Rc<TypeInfo>,
225 ) -> Result<Rc<T>, Error> {
226 read_rc::<T, C>(context, ref_mode, false, Some(type_info))
227 }
228
229 #[inline(always)]
230 fn default_value(context: &mut ReadContext) -> Result<Rc<T>, Error> {
231 check_child::<T, C>()?;
232 reserve_rc::<T>(context)?;
233 Ok(Rc::new(C::default_value(context)?))
234 }
235
236 #[inline(always)]
237 fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
238 C::write_type_info(context)
239 }
240
241 #[inline(always)]
242 fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
243 C::read_type_info(context)
244 }
245
246 #[inline(always)]
247 fn static_type_id() -> TypeId {
248 C::static_type_id()
249 }
250
251 #[inline(always)]
252 fn metadata_target_type_id() -> std::any::TypeId {
253 C::metadata_target_type_id()
254 }
255
256 const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
257
258 const IS_SHARED_REF: bool = true;
259
260 const IS_WRAPPER: bool = true;
261
262 const REQUIRES_SCOPED_ACCESS: bool = C::REQUIRES_SCOPED_ACCESS;
263
264 #[inline(always)]
265 fn dynamic_type_id(value: &Rc<T>) -> Result<Option<std::any::TypeId>, Error> {
266 C::dynamic_type_id(value)
267 }
268}
269
270impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<Rc<T>>
271 for RcCodec<T, C, NULLABLE, TRACK_REF>
272where
273 T: 'static,
274 C: Codec<T>,
275{
276 #[inline(always)]
277 fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
278 let mut field_type = C::field_type(type_resolver)?;
279 field_type.nullable = NULLABLE;
280 field_type.track_ref = TRACK_REF;
281 Ok(field_type)
282 }
283
284 #[inline(always)]
285 fn write_field(value: &Rc<T>, context: &mut WriteContext) -> Result<(), Error> {
286 Self::write_with_mode(
287 value,
288 context,
289 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
290 codec_write_type_info::<T, C>(context),
291 true,
292 )
293 }
294
295 #[inline(always)]
296 fn read_field(context: &mut ReadContext) -> Result<Rc<T>, Error> {
297 <Self as Serializer>::read(
298 context,
299 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
300 codec_read_type_info_static::<T, C>(context),
301 )
302 }
303
304 #[inline(always)]
305 fn read_data_with_type(
306 context: &mut ReadContext,
307 remote_data_type: &FieldType,
308 ) -> Result<Rc<T>, Error> {
309 check_child::<T, C>()?;
310 reserve_rc::<T>(context)?;
311 Ok(Rc::new(C::read_data_with_type(context, remote_data_type)?))
312 }
313
314 #[inline(always)]
315 fn read_field_with_type(
316 context: &mut ReadContext,
317 remote_field_type: &FieldType,
318 ) -> Result<Rc<T>, Error> {
319 read_rc_with_type::<T, C>(
320 context,
321 field_ref_mode(remote_field_type),
322 remote_field_type,
323 )
324 }
325
326 #[inline(always)]
327 fn write_with_mode(
328 value: &Rc<T>,
329 context: &mut WriteContext,
330 ref_mode: RefMode,
331 write_type_info: bool,
332 has_generics: bool,
333 ) -> Result<(), Error> {
334 if !write_ref(value, context, ref_mode) {
335 return Ok(());
336 }
337 write_inner_field::<T, C>(value, context, write_type_info, has_generics)
338 }
339
340 #[inline(always)]
341 fn write_with_type_info(
342 value: &Rc<T>,
343 context: &mut WriteContext,
344 ref_mode: RefMode,
345 type_info: &Rc<TypeInfo>,
346 has_generics: bool,
347 ) -> Result<(), Error> {
348 if !write_ref(value, context, ref_mode) {
349 return Ok(());
350 }
351 write_inner_field_with_type_info::<T, C>(value, context, type_info, has_generics)
352 }
353
354 #[inline(always)]
355 fn read_type_info_value(
356 context: &mut ReadContext,
357 ) -> Result<super::codec::CodecReadType, Error> {
358 C::read_type_info_value(context)
359 }
360}
361
362macro_rules! read_rc_owner {
363 ($context:ident, $ref_mode:expr, $read_inner:expr, $default:expr) => {
364 match $ref_mode {
365 RefMode::None => Ok(Rc::new($read_inner?)),
366 RefMode::NullOnly => {
367 if $context.reader.read_i8()? == RefFlag::Null as i8 {
368 return $default;
369 }
370 Ok(Rc::new($read_inner?))
371 }
372 RefMode::Tracking => match $context.ref_reader.read_ref_flag(&mut $context.reader)? {
373 RefFlag::Null => $default,
374 RefFlag::Ref => {
375 let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
376 $context
377 .ref_reader
378 .get_rc_ref::<T>(ref_id)
379 .ok_or_else(|| missing_rc_ref(ref_id))
380 }
381 RefFlag::NotNullValue => Ok(Rc::new($read_inner?)),
382 RefFlag::RefValue => {
383 let ref_id = $context.ref_reader.reserve_ref_id();
384 let value = Rc::new($read_inner?);
385 $context.ref_reader.store_rc_ref_at(ref_id, value.clone());
386 Ok(value)
387 }
388 },
389 }
390 };
391}
392
393#[inline(always)]
394fn read_rc<T: 'static, C: Serializer<Target = T>>(
395 context: &mut ReadContext,
396 ref_mode: RefMode,
397 read_type_info: bool,
398 type_info: Option<&Rc<TypeInfo>>,
399) -> Result<Rc<T>, Error> {
400 read_rc_owner!(
401 context,
402 ref_mode,
403 read_inner::<T, C>(context, read_type_info, type_info),
404 <RcCodec<T, C, false, false> as Serializer>::default_value(context)
405 )
406}
407
408#[inline(always)]
409fn read_rc_with_type<T: 'static, C: Codec<T>>(
410 context: &mut ReadContext,
411 ref_mode: RefMode,
412 remote_field_type: &FieldType,
413) -> Result<Rc<T>, Error> {
414 read_rc_owner!(
415 context,
416 ref_mode,
417 read_inner_with_type::<T, C>(context, remote_field_type),
418 <RcCodec<T, C, false, false> as Serializer>::default_value(context)
419 )
420}
421
422impl_single_carrier_serializer!(RcSerializer, Rc, RcCodec, wrapper = true);