Skip to main content

fory_core/serializer/
trait_object.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 std::any::Any;
19
20/// Object-safe access to a concrete target's [`Any`] identity.
21///
22/// Application traits serialized by [`crate::register_trait_type!`] extend this
23/// trait instead of extending [`crate::Serializer`].
24pub trait ForyObject: Any {
25    fn as_any(&self) -> &dyn Any;
26}
27
28impl<T: Any> ForyObject for T {
29    #[inline(always)]
30    fn as_any(&self) -> &dyn Any {
31        self
32    }
33}
34
35/// Generates serializers for a closed set of concrete application-trait targets.
36///
37/// The listed types are runtime target types. Their registered ordinary serializer,
38/// external structural serializer, or custom serializer determines wire behavior.
39///
40/// ```rust,ignore
41/// use fory::{register_trait_type, ForyObject};
42///
43/// trait Animal: ForyObject {
44///     fn name(&self) -> &str;
45/// }
46///
47/// register_trait_type!(Animal, Dog, third_party::Cat);
48/// ```
49///
50/// Use `sync` when the application trait and all targets are `Send + Sync`:
51///
52/// ```rust,ignore
53/// register_trait_type!(sync Animal, Dog, third_party::Cat);
54/// ```
55///
56/// Generated serializer and codec names are private by default. Prefix the trait
57/// with a Rust visibility when those names must be exported:
58///
59/// ```rust,ignore
60/// register_trait_type!(pub Animal, Dog, third_party::Cat);
61/// register_trait_type!(pub sync SharedAnimal, Dog, third_party::Cat);
62/// ```
63#[macro_export]
64macro_rules! register_trait_type {
65    ($vis:vis sync $trait_name:ident, $($target:ty),+ $(,)?) => {
66        $crate::register_trait_type!(@dispatch $trait_name, $($target),+);
67        $crate::register_trait_type!(@box [$vis] $trait_name, $($target),+);
68        $crate::register_trait_type!(@rc [$vis] $trait_name, $($target),+);
69        $crate::register_trait_type!(@arc [$vis] $trait_name, $($target),+);
70    };
71
72    ($vis:vis $trait_name:ident, $($target:ty),+ $(,)?) => {
73        $crate::register_trait_type!(@dispatch $trait_name, $($target),+);
74        $crate::register_trait_type!(@box [$vis] $trait_name, $($target),+);
75        $crate::register_trait_type!(@rc [$vis] $trait_name, $($target),+);
76    };
77
78    (@dispatch $trait_name:ident, $($target:ty),+) => {
79        $crate::paste::paste! {
80            #[allow(dead_code)]
81            struct [<$trait_name ForyDispatch>];
82
83            #[allow(dead_code)]
84            impl [<$trait_name ForyDispatch>] {
85                #[inline(always)]
86                fn any_ref(value: &dyn $trait_name) -> &dyn std::any::Any {
87                    <dyn $trait_name as $crate::ForyObject>::as_any(value)
88                }
89
90                #[inline(always)]
91                fn ensure_member(
92                    target_type_id: std::any::TypeId,
93                ) -> Result<(), $crate::Error> {
94                    if !($(target_type_id == std::any::TypeId::of::<$target>())||+) {
95                        return Err(Self::unlisted(target_type_id));
96                    }
97                    Ok(())
98                }
99
100                #[inline(always)]
101                fn checked_any(
102                    value: &dyn $trait_name,
103                ) -> Result<&dyn std::any::Any, $crate::Error> {
104                    let any = Self::any_ref(value);
105                    Self::ensure_member(any.type_id())?;
106                    Ok(any)
107                }
108
109                #[inline(always)]
110                fn target_id(
111                    type_info: &$crate::TypeInfo,
112                ) -> Result<std::any::TypeId, $crate::Error> {
113                    type_info
114                        .get_harness()
115                        .target_type_id()
116                        .ok_or_else(Self::missing)
117                }
118
119                #[inline(always)]
120                fn check_type_info(
121                    target_type_id: std::any::TypeId,
122                    type_info: &$crate::TypeInfo,
123                ) -> Result<(), $crate::Error> {
124                    $crate::serializer::any::check_erased_target_type(type_info)?;
125                    let resolved_target_type_id = Self::target_id(type_info)?;
126                    if resolved_target_type_id != target_type_id {
127                        return Err(Self::downcast(
128                            resolved_target_type_id,
129                            target_type_id,
130                        ));
131                    }
132                    Ok(())
133                }
134
135                #[inline(always)]
136                fn resolve_type_info(
137                    context: &mut $crate::WriteContext,
138                    target_type_id: std::any::TypeId,
139                ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
140                    let type_info = context.get_target_type_info(&target_type_id)?;
141                    Self::check_type_info(target_type_id, &type_info)?;
142                    Ok(type_info)
143                }
144
145                #[inline(always)]
146                fn write_type_info_value(
147                    context: &mut $crate::WriteContext,
148                    target_type_id: std::any::TypeId,
149                ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
150                    Self::ensure_member(target_type_id)?;
151                    let type_info = Self::resolve_type_info(context, target_type_id)?;
152                    context.write_resolved_type_info(
153                        $crate::TypeId::UNKNOWN as u32,
154                        type_info,
155                    )
156                }
157
158                #[inline(always)]
159                fn write_harness(
160                    any: &dyn std::any::Any,
161                    context: &mut $crate::WriteContext,
162                    type_info: &std::rc::Rc<$crate::TypeInfo>,
163                ) -> Result<(), $crate::Error> {
164                    type_info.get_harness().write_data(any, context)
165                }
166
167                #[inline(always)]
168                fn write_checked(
169                    any: &dyn std::any::Any,
170                    context: &mut $crate::WriteContext,
171                    write_type_info: bool,
172                ) -> Result<(), $crate::Error> {
173                    let type_info = Self::resolve_type_info(context, any.type_id())?;
174                    let type_info = if write_type_info {
175                        context.write_resolved_type_info(
176                            $crate::TypeId::UNKNOWN as u32,
177                            type_info,
178                        )?
179                    } else {
180                        type_info
181                    };
182                    Self::write_harness(any, context, &type_info)
183                }
184
185                #[inline(always)]
186                fn write_data(
187                    value: &dyn $trait_name,
188                    context: &mut $crate::WriteContext,
189                    write_type_info: bool,
190                ) -> Result<(), $crate::Error> {
191                    let any = Self::checked_any(value)?;
192                    Self::write_checked(any, context, write_type_info)
193                }
194
195                #[inline(always)]
196                fn read_box(
197                    context: &mut $crate::ReadContext,
198                    type_info: &std::rc::Rc<$crate::TypeInfo>,
199                ) -> Result<Box<dyn $trait_name>, $crate::Error> {
200                    let target_type_id = Self::target_id(type_info)?;
201                    $crate::serializer::any::check_erased_target_type(type_info)?;
202                    $(
203                        if target_type_id == std::any::TypeId::of::<$target>() {
204                            let erased = type_info
205                                .get_harness()
206                                .read_box_any(context, type_info)?;
207                            let concrete = erased.downcast::<$target>().map_err(|value| {
208                                Self::downcast(target_type_id, value.as_ref().type_id())
209                            })?;
210                            let value: Box<dyn $trait_name> = concrete;
211                            return Ok(value);
212                        }
213                    )+
214                    Err(Self::unlisted(target_type_id))
215                }
216
217                #[inline(always)]
218                fn read_rc(
219                    context: &mut $crate::ReadContext,
220                    type_info: &std::rc::Rc<$crate::TypeInfo>,
221                ) -> Result<std::rc::Rc<dyn $trait_name>, $crate::Error> {
222                    let target_type_id = Self::target_id(type_info)?;
223                    $crate::serializer::any::check_erased_target_type(type_info)?;
224                    $(
225                        if target_type_id == std::any::TypeId::of::<$target>() {
226                            let erased = type_info
227                                .get_harness()
228                                .read_rc_any(context, type_info)?;
229                            let concrete = erased.downcast::<$target>().map_err(|value| {
230                                Self::downcast(target_type_id, value.as_ref().type_id())
231                            })?;
232                            let value: std::rc::Rc<dyn $trait_name> = concrete;
233                            return Ok(value);
234                        }
235                    )+
236                    Err(Self::unlisted(target_type_id))
237                }
238
239                #[cold]
240                #[inline(never)]
241                fn unlisted(target_type_id: std::any::TypeId) -> $crate::Error {
242                    $crate::Error::type_error(format!(
243                        "target TypeId {:?} is not listed for application trait {}",
244                        target_type_id,
245                        stringify!($trait_name),
246                    ))
247                }
248
249                #[cold]
250                #[inline(never)]
251                fn missing() -> $crate::Error {
252                    $crate::Error::type_error(format!(
253                        "application trait {} metadata has no checked local target registration",
254                        stringify!($trait_name),
255                    ))
256                }
257
258                #[cold]
259                #[inline(never)]
260                fn downcast(
261                    expected: std::any::TypeId,
262                    actual: std::any::TypeId,
263                ) -> $crate::Error {
264                    $crate::Error::type_error(format!(
265                        "application trait {} expected target TypeId {:?}, got {:?}",
266                        stringify!($trait_name),
267                        expected,
268                        actual,
269                    ))
270                }
271
272                #[cold]
273                #[inline(never)]
274                fn missing_ref(ref_id: u32) -> $crate::Error {
275                    $crate::Error::invalid_data(format!(
276                        "dyn {} reference {} not found",
277                        stringify!($trait_name),
278                        ref_id,
279                    ))
280                }
281            }
282        }
283    };
284
285    (@box [$vis:vis] $trait_name:ident, $($target:ty),+) => {
286        $crate::paste::paste! {
287            #[allow(dead_code)]
288            impl [<$trait_name ForyDispatch>] {
289                #[cold]
290                #[inline(never)]
291                fn null_box_value() -> $crate::Error {
292                    $crate::Error::invalid_ref(concat!(
293                        "Box<dyn ",
294                        stringify!($trait_name),
295                        "> cannot be null",
296                    ))
297                }
298
299                #[cold]
300                #[inline(never)]
301                fn missing_box_metadata() -> $crate::Error {
302                    $crate::Error::invalid_data(concat!(
303                        "Box<dyn ",
304                        stringify!($trait_name),
305                        "> requires concrete type metadata",
306                    ))
307                }
308            }
309
310            impl $crate::Serializer for Box<dyn $trait_name> {
311                type Target = Self;
312                #[inline(always)]
313                fn write_data(
314                    value: &Self,
315                    context: &mut $crate::WriteContext,
316                ) -> Result<(), $crate::Error> {
317                    [<$trait_name ForyDispatch>]::write_data(
318                        value.as_ref(),
319                        context,
320                        false,
321                    )
322                }
323
324                #[cold]
325                #[inline(never)]
326                fn read_data(
327                    _context: &mut $crate::ReadContext,
328                ) -> Result<Self, $crate::Error> {
329                    Err($crate::Error::not_allowed(concat!(
330                        "Box<dyn ",
331                        stringify!($trait_name),
332                        "> requires concrete type metadata",
333                    )))
334                }
335
336                #[inline(always)]
337                fn write_type_info_value(
338                    context: &mut $crate::WriteContext,
339                    target_type_id: std::any::TypeId,
340                ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
341                    [<$trait_name ForyDispatch>]::write_type_info_value(
342                        context,
343                        target_type_id,
344                    )
345                }
346
347                #[inline(always)]
348                fn write_with_type_info(
349                    value: &Self,
350                    context: &mut $crate::WriteContext,
351                    ref_mode: $crate::RefMode,
352                    type_info: &std::rc::Rc<$crate::TypeInfo>,
353                ) -> Result<(), $crate::Error> {
354                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
355                    [<$trait_name ForyDispatch>]::check_type_info(any.type_id(), type_info)?;
356                    if ref_mode != $crate::RefMode::None {
357                        context.writer.write_i8($crate::RefFlag::NotNullValue as i8);
358                    }
359                    [<$trait_name ForyDispatch>]::write_harness(
360                        any,
361                        context,
362                        type_info,
363                    )
364                }
365
366                #[inline(always)]
367                fn write(
368                    value: &Self,
369                    context: &mut $crate::WriteContext,
370                    ref_mode: $crate::RefMode,
371                    write_type_info: bool,
372                ) -> Result<(), $crate::Error> {
373                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
374                    if ref_mode != $crate::RefMode::None {
375                        context.writer.write_i8($crate::RefFlag::NotNullValue as i8);
376                    }
377                    [<$trait_name ForyDispatch>]::write_checked(
378                        any,
379                        context,
380                        write_type_info,
381                    )
382                }
383
384                #[inline(always)]
385                fn read(
386                    context: &mut $crate::ReadContext,
387                    ref_mode: $crate::RefMode,
388                    read_type_info: bool,
389                ) -> Result<Self, $crate::Error> {
390                    context.inc_depth()?;
391                    let value = (|| {
392                        if ref_mode != $crate::RefMode::None
393                            && context.reader.read_i8()?
394                                != $crate::RefFlag::NotNullValue as i8
395                        {
396                            return Err([<$trait_name ForyDispatch>]::null_box_value());
397                        }
398                        if !read_type_info {
399                            return Err([<$trait_name ForyDispatch>]::missing_box_metadata());
400                        }
401                        let type_info = context.read_any_type_info()?;
402                        [<$trait_name ForyDispatch>]::read_box(context, &type_info)
403                    })()?;
404                    context.dec_depth();
405                    Ok(value)
406                }
407
408                #[inline(always)]
409                fn read_with_type_info(
410                    context: &mut $crate::ReadContext,
411                    ref_mode: $crate::RefMode,
412                    type_info: &std::rc::Rc<$crate::TypeInfo>,
413                ) -> Result<Self, $crate::Error> {
414                    context.inc_depth()?;
415                    let value = (|| {
416                        if ref_mode != $crate::RefMode::None
417                            && context.reader.read_i8()?
418                                != $crate::RefFlag::NotNullValue as i8
419                        {
420                            return Err([<$trait_name ForyDispatch>]::null_box_value());
421                        }
422                        [<$trait_name ForyDispatch>]::read_box(context, type_info)
423                    })()?;
424                    context.dec_depth();
425                    Ok(value)
426                }
427
428                #[inline(always)]
429                fn write_type_info(
430                    _context: &mut $crate::WriteContext,
431                ) -> Result<(), $crate::Error> {
432                    Ok(())
433                }
434
435                #[inline(always)]
436                fn read_type_info(
437                    _context: &mut $crate::ReadContext,
438                ) -> Result<(), $crate::Error> {
439                    Ok(())
440                }
441
442                #[inline(always)]
443                fn static_type_id() -> $crate::TypeId {
444                    $crate::TypeId::UNKNOWN
445                }
446
447                #[inline(always)]
448                fn reserved_space() -> usize {
449                    $crate::type_id::SIZE_OF_REF_AND_TYPE
450                }
451
452                const IS_POLYMORPHIC: bool = true;
453
454                const IS_WRAPPER: bool = true;
455
456                #[inline(always)]
457                fn dynamic_type_id(
458                    value: &Self,
459                ) -> Result<Option<std::any::TypeId>, $crate::Error> {
460                    Ok(Some(
461                        [<$trait_name ForyDispatch>]::any_ref(value.as_ref()).type_id(),
462                    ))
463                }
464            }
465
466            $crate::register_trait_type!(
467                @codec
468                [$vis]
469                [<$trait_name BoxCodec>],
470                Box<dyn $trait_name>,
471                Box<dyn $trait_name>
472            );
473        }
474    };
475
476    (@rc [$vis:vis] $trait_name:ident, $($target:ty),+) => {
477        $crate::paste::paste! {
478            #[allow(dead_code)]
479            impl [<$trait_name ForyDispatch>] {
480                #[cold]
481                #[inline(never)]
482                fn null_rc_value() -> $crate::Error {
483                    $crate::Error::invalid_ref(concat!(
484                        "Rc<dyn ",
485                        stringify!($trait_name),
486                        "> cannot be null",
487                    ))
488                }
489
490                #[cold]
491                #[inline(never)]
492                fn missing_rc_metadata() -> $crate::Error {
493                    $crate::Error::invalid_data(concat!(
494                        "Rc<dyn ",
495                        stringify!($trait_name),
496                        "> requires concrete type metadata",
497                    ))
498                }
499            }
500
501            #[allow(dead_code)]
502            #[doc = concat!("Serializer for `Rc<dyn ", stringify!($trait_name), ">`.")]
503            $vis struct [<$trait_name RcSerializer>](std::marker::PhantomData<()>);
504
505            impl $crate::Serializer for [<$trait_name RcSerializer>] {
506                type Target = std::rc::Rc<dyn $trait_name>;
507                #[inline(always)]
508                fn write_data(
509                    value: &Self::Target,
510                    context: &mut $crate::WriteContext,
511                ) -> Result<(), $crate::Error> {
512                    [<$trait_name ForyDispatch>]::write_data(
513                        value.as_ref(),
514                        context,
515                        false,
516                    )
517                }
518
519                #[cold]
520                #[inline(never)]
521                fn read_data(
522                    _context: &mut $crate::ReadContext,
523                ) -> Result<Self::Target, $crate::Error> {
524                    Err($crate::Error::not_allowed(concat!(
525                        "Rc<dyn ",
526                        stringify!($trait_name),
527                        "> requires concrete type metadata",
528                    )))
529                }
530
531                #[inline(always)]
532                fn write_type_info_value(
533                    context: &mut $crate::WriteContext,
534                    target_type_id: std::any::TypeId,
535                ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
536                    [<$trait_name ForyDispatch>]::write_type_info_value(
537                        context,
538                        target_type_id,
539                    )
540                }
541
542                #[inline(always)]
543                fn write_with_type_info(
544                    value: &Self::Target,
545                    context: &mut $crate::WriteContext,
546                    ref_mode: $crate::RefMode,
547                    type_info: &std::rc::Rc<$crate::TypeInfo>,
548                ) -> Result<(), $crate::Error> {
549                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
550                    [<$trait_name ForyDispatch>]::check_type_info(any.type_id(), type_info)?;
551                    if ref_mode != $crate::RefMode::None
552                        && context
553                            .ref_writer
554                            .try_write_rc_ref(&mut context.writer, value)
555                    {
556                        return Ok(());
557                    }
558                    [<$trait_name ForyDispatch>]::write_harness(
559                        any,
560                        context,
561                        type_info,
562                    )
563                }
564
565                #[inline(always)]
566                fn write(
567                    value: &Self::Target,
568                    context: &mut $crate::WriteContext,
569                    ref_mode: $crate::RefMode,
570                    write_type_info: bool,
571                ) -> Result<(), $crate::Error> {
572                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
573                    if ref_mode != $crate::RefMode::None
574                        && context
575                            .ref_writer
576                            .try_write_rc_ref(&mut context.writer, value)
577                    {
578                        return Ok(());
579                    }
580                    [<$trait_name ForyDispatch>]::write_checked(
581                        any,
582                        context,
583                        write_type_info,
584                    )
585                }
586
587                #[inline(always)]
588                fn read(
589                    context: &mut $crate::ReadContext,
590                    ref_mode: $crate::RefMode,
591                    read_type_info: bool,
592                ) -> Result<Self::Target, $crate::Error> {
593                    let ref_flag = if ref_mode != $crate::RefMode::None {
594                        context.ref_reader.read_ref_flag(&mut context.reader)?
595                    } else {
596                        $crate::RefFlag::NotNullValue
597                    };
598                    match ref_flag {
599                        $crate::RefFlag::Null => {
600                            Err([<$trait_name ForyDispatch>]::null_rc_value())
601                        }
602                        $crate::RefFlag::Ref => {
603                            let ref_id =
604                                context.ref_reader.read_ref_id(&mut context.reader)?;
605                            context
606                                .ref_reader
607                                .get_rc_ref::<dyn $trait_name>(ref_id)
608                                .ok_or_else(|| {
609                                    [<$trait_name ForyDispatch>]::missing_ref(ref_id)
610                                })
611                        }
612                        $crate::RefFlag::NotNullValue => {
613                            context.inc_depth()?;
614                            let value = (|| {
615                                if !read_type_info {
616                                    return Err(
617                                        [<$trait_name ForyDispatch>]::missing_rc_metadata()
618                                    );
619                                }
620                                let type_info = context.read_any_type_info()?;
621                                [<$trait_name ForyDispatch>]::read_rc(context, &type_info)
622                            })()?;
623                            context.dec_depth();
624                            Ok(value)
625                        }
626                        $crate::RefFlag::RefValue => {
627                            let ref_id = context.ref_reader.reserve_ref_id();
628                            context.inc_depth()?;
629                            let value = (|| {
630                                if !read_type_info {
631                                    return Err(
632                                        [<$trait_name ForyDispatch>]::missing_rc_metadata()
633                                    );
634                                }
635                                let type_info = context.read_any_type_info()?;
636                                [<$trait_name ForyDispatch>]::read_rc(context, &type_info)
637                            })()?;
638                            context.dec_depth();
639                            context.ref_reader.store_rc_ref_at(ref_id, value.clone());
640                            Ok(value)
641                        }
642                    }
643                }
644
645                #[inline(always)]
646                fn read_with_type_info(
647                    context: &mut $crate::ReadContext,
648                    ref_mode: $crate::RefMode,
649                    type_info: &std::rc::Rc<$crate::TypeInfo>,
650                ) -> Result<Self::Target, $crate::Error> {
651                    let ref_flag = if ref_mode != $crate::RefMode::None {
652                        context.ref_reader.read_ref_flag(&mut context.reader)?
653                    } else {
654                        $crate::RefFlag::NotNullValue
655                    };
656                    match ref_flag {
657                        $crate::RefFlag::Null => {
658                            Err([<$trait_name ForyDispatch>]::null_rc_value())
659                        }
660                        $crate::RefFlag::Ref => {
661                            let ref_id =
662                                context.ref_reader.read_ref_id(&mut context.reader)?;
663                            context
664                                .ref_reader
665                                .get_rc_ref::<dyn $trait_name>(ref_id)
666                                .ok_or_else(|| {
667                                    [<$trait_name ForyDispatch>]::missing_ref(ref_id)
668                                })
669                        }
670                        $crate::RefFlag::NotNullValue => {
671                            context.inc_depth()?;
672                            let value =
673                                [<$trait_name ForyDispatch>]::read_rc(context, type_info)?;
674                            context.dec_depth();
675                            Ok(value)
676                        }
677                        $crate::RefFlag::RefValue => {
678                            let ref_id = context.ref_reader.reserve_ref_id();
679                            context.inc_depth()?;
680                            let value =
681                                [<$trait_name ForyDispatch>]::read_rc(context, type_info)?;
682                            context.dec_depth();
683                            context.ref_reader.store_rc_ref_at(ref_id, value.clone());
684                            Ok(value)
685                        }
686                    }
687                }
688
689                #[inline(always)]
690                fn write_type_info(
691                    _context: &mut $crate::WriteContext,
692                ) -> Result<(), $crate::Error> {
693                    Ok(())
694                }
695
696                #[inline(always)]
697                fn read_type_info(
698                    _context: &mut $crate::ReadContext,
699                ) -> Result<(), $crate::Error> {
700                    Ok(())
701                }
702
703                #[inline(always)]
704                fn static_type_id() -> $crate::TypeId {
705                    $crate::TypeId::UNKNOWN
706                }
707
708                #[inline(always)]
709                fn reserved_space() -> usize {
710                    $crate::type_id::SIZE_OF_REF_AND_TYPE
711                }
712
713                const IS_POLYMORPHIC: bool = true;
714
715                const IS_SHARED_REF: bool = true;
716
717                const IS_WRAPPER: bool = true;
718
719                #[inline(always)]
720                fn dynamic_type_id(
721                    value: &Self::Target,
722                ) -> Result<Option<std::any::TypeId>, $crate::Error> {
723                    Ok(Some(
724                        [<$trait_name ForyDispatch>]::any_ref(value.as_ref()).type_id(),
725                    ))
726                }
727            }
728
729            $crate::register_trait_type!(
730                @codec
731                [$vis]
732                [<$trait_name RcCodec>],
733                [<$trait_name RcSerializer>],
734                std::rc::Rc<dyn $trait_name>
735            );
736        }
737    };
738
739    (@arc [$vis:vis] $trait_name:ident, $($target:ty),+) => {
740        $crate::paste::paste! {
741            const _: () = {
742                fn assert_sync<T: ?Sized + Send + Sync>() {}
743                let _ = assert_sync::<dyn $trait_name>;
744                $(let _ = assert_sync::<$target>;)+
745            };
746
747            #[allow(dead_code)]
748            impl [<$trait_name ForyDispatch>] {
749                #[cold]
750                #[inline(never)]
751                fn null_arc_value() -> $crate::Error {
752                    $crate::Error::invalid_ref(concat!(
753                        "Arc<dyn ",
754                        stringify!($trait_name),
755                        "> cannot be null",
756                    ))
757                }
758
759                #[cold]
760                #[inline(never)]
761                fn missing_arc_metadata() -> $crate::Error {
762                    $crate::Error::invalid_data(concat!(
763                        "Arc<dyn ",
764                        stringify!($trait_name),
765                        "> requires concrete type metadata",
766                    ))
767                }
768
769                #[inline(always)]
770                fn read_arc(
771                    context: &mut $crate::ReadContext,
772                    type_info: &std::rc::Rc<$crate::TypeInfo>,
773                ) -> Result<std::sync::Arc<dyn $trait_name>, $crate::Error> {
774                    let target_type_id = Self::target_id(type_info)?;
775                    $crate::serializer::any::check_erased_target_type(type_info)?;
776                    $(
777                        if target_type_id == std::any::TypeId::of::<$target>() {
778                            let erased = type_info
779                                .get_harness()
780                                .read_arc_any(context, type_info)?;
781                            let concrete = erased.downcast::<$target>().map_err(|value| {
782                                Self::downcast(target_type_id, value.as_ref().type_id())
783                            })?;
784                            let value: std::sync::Arc<dyn $trait_name> = concrete;
785                            return Ok(value);
786                        }
787                    )+
788                    Err(Self::unlisted(target_type_id))
789                }
790            }
791
792            #[allow(dead_code)]
793            #[doc = concat!("Serializer for `Arc<dyn ", stringify!($trait_name), ">`.")]
794            $vis struct [<$trait_name ArcSerializer>](std::marker::PhantomData<()>);
795
796            impl $crate::Serializer for [<$trait_name ArcSerializer>] {
797                type Target = std::sync::Arc<dyn $trait_name>;
798                #[inline(always)]
799                fn write_data(
800                    value: &Self::Target,
801                    context: &mut $crate::WriteContext,
802                ) -> Result<(), $crate::Error> {
803                    [<$trait_name ForyDispatch>]::write_data(
804                        value.as_ref(),
805                        context,
806                        false,
807                    )
808                }
809
810                #[cold]
811                #[inline(never)]
812                fn read_data(
813                    _context: &mut $crate::ReadContext,
814                ) -> Result<Self::Target, $crate::Error> {
815                    Err($crate::Error::not_allowed(concat!(
816                        "Arc<dyn ",
817                        stringify!($trait_name),
818                        "> requires concrete type metadata",
819                    )))
820                }
821
822                #[inline(always)]
823                fn write_type_info_value(
824                    context: &mut $crate::WriteContext,
825                    target_type_id: std::any::TypeId,
826                ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
827                    [<$trait_name ForyDispatch>]::write_type_info_value(
828                        context,
829                        target_type_id,
830                    )
831                }
832
833                #[inline(always)]
834                fn write_with_type_info(
835                    value: &Self::Target,
836                    context: &mut $crate::WriteContext,
837                    ref_mode: $crate::RefMode,
838                    type_info: &std::rc::Rc<$crate::TypeInfo>,
839                ) -> Result<(), $crate::Error> {
840                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
841                    [<$trait_name ForyDispatch>]::check_type_info(any.type_id(), type_info)?;
842                    if ref_mode != $crate::RefMode::None
843                        && context
844                            .ref_writer
845                            .try_write_arc_ref(&mut context.writer, value)
846                    {
847                        return Ok(());
848                    }
849                    [<$trait_name ForyDispatch>]::write_harness(
850                        any,
851                        context,
852                        type_info,
853                    )
854                }
855
856                #[inline(always)]
857                fn write(
858                    value: &Self::Target,
859                    context: &mut $crate::WriteContext,
860                    ref_mode: $crate::RefMode,
861                    write_type_info: bool,
862                ) -> Result<(), $crate::Error> {
863                    let any = [<$trait_name ForyDispatch>]::checked_any(value.as_ref())?;
864                    if ref_mode != $crate::RefMode::None
865                        && context
866                            .ref_writer
867                            .try_write_arc_ref(&mut context.writer, value)
868                    {
869                        return Ok(());
870                    }
871                    [<$trait_name ForyDispatch>]::write_checked(
872                        any,
873                        context,
874                        write_type_info,
875                    )
876                }
877
878                #[inline(always)]
879                fn read(
880                    context: &mut $crate::ReadContext,
881                    ref_mode: $crate::RefMode,
882                    read_type_info: bool,
883                ) -> Result<Self::Target, $crate::Error> {
884                    let ref_flag = if ref_mode != $crate::RefMode::None {
885                        context.ref_reader.read_ref_flag(&mut context.reader)?
886                    } else {
887                        $crate::RefFlag::NotNullValue
888                    };
889                    match ref_flag {
890                        $crate::RefFlag::Null => {
891                            Err([<$trait_name ForyDispatch>]::null_arc_value())
892                        }
893                        $crate::RefFlag::Ref => {
894                            let ref_id =
895                                context.ref_reader.read_ref_id(&mut context.reader)?;
896                            context
897                                .ref_reader
898                                .get_arc_ref::<dyn $trait_name>(ref_id)
899                                .ok_or_else(|| {
900                                    [<$trait_name ForyDispatch>]::missing_ref(ref_id)
901                                })
902                        }
903                        $crate::RefFlag::NotNullValue => {
904                            context.inc_depth()?;
905                            let value = (|| {
906                                if !read_type_info {
907                                    return Err(
908                                        [<$trait_name ForyDispatch>]::missing_arc_metadata()
909                                    );
910                                }
911                                let type_info = context.read_any_type_info()?;
912                                [<$trait_name ForyDispatch>]::read_arc(context, &type_info)
913                            })()?;
914                            context.dec_depth();
915                            Ok(value)
916                        }
917                        $crate::RefFlag::RefValue => {
918                            let ref_id = context.ref_reader.reserve_ref_id();
919                            context.inc_depth()?;
920                            let value = (|| {
921                                if !read_type_info {
922                                    return Err(
923                                        [<$trait_name ForyDispatch>]::missing_arc_metadata()
924                                    );
925                                }
926                                let type_info = context.read_any_type_info()?;
927                                [<$trait_name ForyDispatch>]::read_arc(context, &type_info)
928                            })()?;
929                            context.dec_depth();
930                            context.ref_reader.store_arc_ref_at(ref_id, value.clone());
931                            Ok(value)
932                        }
933                    }
934                }
935
936                #[inline(always)]
937                fn read_with_type_info(
938                    context: &mut $crate::ReadContext,
939                    ref_mode: $crate::RefMode,
940                    type_info: &std::rc::Rc<$crate::TypeInfo>,
941                ) -> Result<Self::Target, $crate::Error> {
942                    let ref_flag = if ref_mode != $crate::RefMode::None {
943                        context.ref_reader.read_ref_flag(&mut context.reader)?
944                    } else {
945                        $crate::RefFlag::NotNullValue
946                    };
947                    match ref_flag {
948                        $crate::RefFlag::Null => {
949                            Err([<$trait_name ForyDispatch>]::null_arc_value())
950                        }
951                        $crate::RefFlag::Ref => {
952                            let ref_id =
953                                context.ref_reader.read_ref_id(&mut context.reader)?;
954                            context
955                                .ref_reader
956                                .get_arc_ref::<dyn $trait_name>(ref_id)
957                                .ok_or_else(|| {
958                                    [<$trait_name ForyDispatch>]::missing_ref(ref_id)
959                                })
960                        }
961                        $crate::RefFlag::NotNullValue => {
962                            context.inc_depth()?;
963                            let value =
964                                [<$trait_name ForyDispatch>]::read_arc(context, type_info)?;
965                            context.dec_depth();
966                            Ok(value)
967                        }
968                        $crate::RefFlag::RefValue => {
969                            let ref_id = context.ref_reader.reserve_ref_id();
970                            context.inc_depth()?;
971                            let value =
972                                [<$trait_name ForyDispatch>]::read_arc(context, type_info)?;
973                            context.dec_depth();
974                            context.ref_reader.store_arc_ref_at(ref_id, value.clone());
975                            Ok(value)
976                        }
977                    }
978                }
979
980                #[inline(always)]
981                fn write_type_info(
982                    _context: &mut $crate::WriteContext,
983                ) -> Result<(), $crate::Error> {
984                    Ok(())
985                }
986
987                #[inline(always)]
988                fn read_type_info(
989                    _context: &mut $crate::ReadContext,
990                ) -> Result<(), $crate::Error> {
991                    Ok(())
992                }
993
994                #[inline(always)]
995                fn static_type_id() -> $crate::TypeId {
996                    $crate::TypeId::UNKNOWN
997                }
998
999                #[inline(always)]
1000                fn reserved_space() -> usize {
1001                    $crate::type_id::SIZE_OF_REF_AND_TYPE
1002                }
1003
1004                const IS_POLYMORPHIC: bool = true;
1005
1006                const IS_SHARED_REF: bool = true;
1007
1008                const IS_WRAPPER: bool = true;
1009
1010                #[inline(always)]
1011                fn dynamic_type_id(
1012                    value: &Self::Target,
1013                ) -> Result<Option<std::any::TypeId>, $crate::Error> {
1014                    Ok(Some(
1015                        [<$trait_name ForyDispatch>]::any_ref(value.as_ref()).type_id(),
1016                    ))
1017                }
1018            }
1019
1020            $crate::register_trait_type!(
1021                @codec
1022                [$vis]
1023                [<$trait_name ArcCodec>],
1024                [<$trait_name ArcSerializer>],
1025                std::sync::Arc<dyn $trait_name>
1026            );
1027        }
1028    };
1029
1030    (@codec [$vis:vis] $codec:ident, $provider:ty, $target:ty) => {
1031        #[allow(dead_code)]
1032        #[doc(hidden)]
1033        $vis struct $codec<const NULLABLE: bool, const TRACK_REF: bool>;
1034
1035        impl<const NULLABLE: bool, const TRACK_REF: bool> $crate::Serializer
1036            for $codec<NULLABLE, TRACK_REF>
1037        {
1038            type Target = $target;
1039
1040            #[inline(always)]
1041            fn write_data(
1042                value: &Self::Target,
1043                context: &mut $crate::WriteContext,
1044            ) -> Result<(), $crate::Error> {
1045                <$provider as $crate::Serializer>::write_data(value, context)
1046            }
1047
1048            #[inline(always)]
1049            fn read_data(
1050                context: &mut $crate::ReadContext,
1051            ) -> Result<Self::Target, $crate::Error> {
1052                <$provider as $crate::Serializer>::read_data(context)
1053            }
1054
1055            #[inline(always)]
1056            fn default_value(
1057                context: &mut $crate::ReadContext,
1058            ) -> Result<Self::Target, $crate::Error> {
1059                <$provider as $crate::Serializer>::default_value(context)
1060            }
1061
1062            #[inline(always)]
1063            fn write(
1064                value: &Self::Target,
1065                context: &mut $crate::WriteContext,
1066                ref_mode: $crate::RefMode,
1067                write_type_info: bool,
1068            ) -> Result<(), $crate::Error> {
1069                <$provider as $crate::Serializer>::write(
1070                    value,
1071                    context,
1072                    ref_mode,
1073                    write_type_info,
1074                )
1075            }
1076
1077            #[inline(always)]
1078            fn write_type_info_value(
1079                context: &mut $crate::WriteContext,
1080                target_type_id: std::any::TypeId,
1081            ) -> Result<std::rc::Rc<$crate::TypeInfo>, $crate::Error> {
1082                <$provider as $crate::Serializer>::write_type_info_value(
1083                    context,
1084                    target_type_id,
1085                )
1086            }
1087
1088            #[inline(always)]
1089            fn write_with_type_info(
1090                value: &Self::Target,
1091                context: &mut $crate::WriteContext,
1092                ref_mode: $crate::RefMode,
1093                type_info: &std::rc::Rc<$crate::TypeInfo>,
1094            ) -> Result<(), $crate::Error> {
1095                <$provider as $crate::Serializer>::write_with_type_info(
1096                    value,
1097                    context,
1098                    ref_mode,
1099                    type_info,
1100                )
1101            }
1102
1103            #[inline(always)]
1104            fn read(
1105                context: &mut $crate::ReadContext,
1106                ref_mode: $crate::RefMode,
1107                read_type_info: bool,
1108            ) -> Result<Self::Target, $crate::Error> {
1109                <$provider as $crate::Serializer>::read(
1110                    context,
1111                    ref_mode,
1112                    read_type_info,
1113                )
1114            }
1115
1116            #[inline(always)]
1117            fn read_with_type_info(
1118                context: &mut $crate::ReadContext,
1119                ref_mode: $crate::RefMode,
1120                type_info: &std::rc::Rc<$crate::TypeInfo>,
1121            ) -> Result<Self::Target, $crate::Error> {
1122                <$provider as $crate::Serializer>::read_with_type_info(
1123                    context,
1124                    ref_mode,
1125                    type_info,
1126                )
1127            }
1128
1129            #[inline(always)]
1130            fn write_type_info(
1131                _context: &mut $crate::WriteContext,
1132            ) -> Result<(), $crate::Error> {
1133                Ok(())
1134            }
1135
1136            #[inline(always)]
1137            fn read_type_info(
1138                _context: &mut $crate::ReadContext,
1139            ) -> Result<(), $crate::Error> {
1140                Ok(())
1141            }
1142
1143            #[inline(always)]
1144            fn static_type_id() -> $crate::TypeId {
1145                $crate::TypeId::UNKNOWN
1146            }
1147
1148            #[inline(always)]
1149            fn reserved_space() -> usize {
1150                <$provider as $crate::Serializer>::reserved_space()
1151            }
1152
1153            const IS_OPTIONAL: bool = <$provider as $crate::Serializer>::IS_OPTIONAL;
1154
1155            const IS_POLYMORPHIC: bool = <$provider as $crate::Serializer>::IS_POLYMORPHIC;
1156
1157            const IS_SHARED_REF: bool = <$provider as $crate::Serializer>::IS_SHARED_REF;
1158
1159            const IS_WRAPPER: bool = <$provider as $crate::Serializer>::IS_WRAPPER;
1160
1161            const REQUIRES_SCOPED_ACCESS: bool =
1162                <$provider as $crate::Serializer>::REQUIRES_SCOPED_ACCESS;
1163
1164            #[inline(always)]
1165            fn dynamic_type_id(
1166                value: &Self::Target,
1167            ) -> Result<Option<std::any::TypeId>, $crate::Error> {
1168                <$provider as $crate::Serializer>::dynamic_type_id(value)
1169            }
1170
1171        }
1172
1173        impl<const NULLABLE: bool, const TRACK_REF: bool>
1174            $crate::serializer::codec::Codec<$target>
1175            for $codec<NULLABLE, TRACK_REF>
1176        {
1177            #[inline(always)]
1178            fn field_type(
1179                _type_resolver: &$crate::TypeResolver,
1180            ) -> Result<$crate::meta::FieldType, $crate::Error> {
1181                Ok($crate::meta::FieldType::new_with_ref(
1182                    $crate::TypeId::UNKNOWN as u32,
1183                    NULLABLE,
1184                    TRACK_REF,
1185                    Vec::new(),
1186                ))
1187            }
1188
1189            #[inline(always)]
1190            fn field_reserved_space() -> usize {
1191                <$provider as $crate::Serializer>::reserved_space()
1192                    + $crate::type_id::SIZE_OF_REF_AND_TYPE
1193            }
1194
1195            #[inline(always)]
1196            fn write_field(
1197                value: &$target,
1198                context: &mut $crate::WriteContext,
1199            ) -> Result<(), $crate::Error> {
1200                <$provider as $crate::Serializer>::write(
1201                    value,
1202                    context,
1203                    if TRACK_REF {
1204                        $crate::RefMode::Tracking
1205                    } else if NULLABLE {
1206                        $crate::RefMode::NullOnly
1207                    } else {
1208                        $crate::RefMode::None
1209                    },
1210                    true,
1211                )
1212            }
1213
1214            #[inline(always)]
1215            fn read_field(
1216                context: &mut $crate::ReadContext,
1217            ) -> Result<$target, $crate::Error> {
1218                <$provider as $crate::Serializer>::read(
1219                    context,
1220                    if TRACK_REF {
1221                        $crate::RefMode::Tracking
1222                    } else if NULLABLE {
1223                        $crate::RefMode::NullOnly
1224                    } else {
1225                        $crate::RefMode::None
1226                    },
1227                    true,
1228                )
1229            }
1230
1231            #[inline(always)]
1232            fn read_field_with_type(
1233                context: &mut $crate::ReadContext,
1234                remote_field_type: &$crate::meta::FieldType,
1235            ) -> Result<$target, $crate::Error> {
1236                <$provider as $crate::Serializer>::read(
1237                    context,
1238                    $crate::serializer::codec::field_ref_mode(remote_field_type),
1239                    true,
1240                )
1241            }
1242
1243            #[inline(always)]
1244            fn write_with_mode(
1245                value: &$target,
1246                context: &mut $crate::WriteContext,
1247                ref_mode: $crate::RefMode,
1248                write_type_info: bool,
1249                _has_generics: bool,
1250            ) -> Result<(), $crate::Error> {
1251                <$provider as $crate::Serializer>::write(
1252                    value,
1253                    context,
1254                    ref_mode,
1255                    write_type_info,
1256                )
1257            }
1258
1259            #[inline(always)]
1260            fn write_with_type_info(
1261                value: &$target,
1262                context: &mut $crate::WriteContext,
1263                ref_mode: $crate::RefMode,
1264                type_info: &std::rc::Rc<$crate::TypeInfo>,
1265                _has_generics: bool,
1266            ) -> Result<(), $crate::Error> {
1267                <$provider as $crate::Serializer>::write_with_type_info(
1268                    value,
1269                    context,
1270                    ref_mode,
1271                    type_info,
1272                )
1273            }
1274
1275            #[inline(always)]
1276            fn read_type_info_value(
1277                context: &mut $crate::ReadContext,
1278            ) -> Result<$crate::serializer::codec::CodecReadType, $crate::Error> {
1279                context
1280                    .read_any_type_info()
1281                    .map($crate::serializer::codec::CodecReadType::TypeInfo)
1282            }
1283        }
1284    };
1285}
1286
1287#[cfg(test)]
1288mod tests {
1289    use crate::{ForyObject, Serializer};
1290    use std::rc::Rc;
1291    use std::sync::Arc;
1292
1293    trait PrivateAnimal: ForyObject {}
1294
1295    struct PrivateDog;
1296
1297    impl PrivateAnimal for PrivateDog {}
1298
1299    register_trait_type!(PrivateAnimal, PrivateDog);
1300
1301    pub mod public_api {
1302        use crate::ForyObject;
1303
1304        pub trait PublicAnimal: ForyObject {}
1305
1306        pub struct PublicDog;
1307
1308        impl PublicAnimal for PublicDog {}
1309
1310        register_trait_type!(pub PublicAnimal, PublicDog);
1311
1312        pub trait SharedAnimal: ForyObject + Send + Sync {}
1313
1314        impl SharedAnimal for PublicDog {}
1315
1316        register_trait_type!(pub sync SharedAnimal, PublicDog);
1317    }
1318
1319    fn assert_target<S, T>()
1320    where
1321        S: Serializer<Target = T>,
1322        T: 'static,
1323    {
1324    }
1325
1326    #[test]
1327    fn trait_visibility_forms_compile() {
1328        assert_target::<PrivateAnimalRcSerializer, Rc<dyn PrivateAnimal>>();
1329        assert_target::<public_api::PublicAnimalRcSerializer, Rc<dyn public_api::PublicAnimal>>();
1330        assert_target::<public_api::SharedAnimalArcSerializer, Arc<dyn public_api::SharedAnimal>>();
1331    }
1332}