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