1#[cfg(feature = "alloc")]
4mod alloc;
5mod core;
6
7use ::core::{error::Error, fmt};
8use rancor::{fail, Fallible, Source, Strategy};
9
10#[cfg(feature = "alloc")]
11pub use self::alloc::*;
12pub use self::core::*;
13use crate::SerializeUnsized;
14
15pub enum SharingState {
17 Started,
20 Pending,
24 Finished(usize),
27}
28
29pub trait Sharing<E = <Self as Fallible>::Error> {
33 fn start_sharing(&mut self, address: usize) -> SharingState;
35
36 fn finish_sharing(&mut self, address: usize, pos: usize) -> Result<(), E>;
40}
41
42impl<T, E> Sharing<E> for &mut T
43where
44 T: Sharing<E> + ?Sized,
45{
46 fn start_sharing(&mut self, address: usize) -> SharingState {
47 T::start_sharing(*self, address)
48 }
49
50 fn finish_sharing(&mut self, address: usize, pos: usize) -> Result<(), E> {
51 T::finish_sharing(*self, address, pos)
52 }
53}
54
55impl<T, E> Sharing<E> for Strategy<T, E>
56where
57 T: Sharing<E> + ?Sized,
58{
59 fn start_sharing(&mut self, address: usize) -> SharingState {
60 T::start_sharing(self, address)
61 }
62
63 fn finish_sharing(&mut self, address: usize, pos: usize) -> Result<(), E> {
64 T::finish_sharing(self, address, pos)
65 }
66}
67
68#[derive(Debug)]
69struct CyclicSharedPointerError;
70
71impl fmt::Display for CyclicSharedPointerError {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(
74 f,
75 "encountered cyclic shared pointers while serializing\nhelp: \
76 change your serialization strategy to `Unshare` or use the \
77 `Unshare` wrapper type to break the cycle",
78 )
79 }
80}
81
82impl Error for CyclicSharedPointerError {}
83
84pub trait SharingExt<E>: Sharing<E> {
86 fn serialize_shared<T: SerializeUnsized<Self> + ?Sized>(
92 &mut self,
93 value: &T,
94 ) -> Result<usize, <Self as Fallible>::Error>
95 where
96 Self: Fallible<Error = E>,
97 E: Source,
98 {
99 let addr = value as *const T as *const () as usize;
100 match self.start_sharing(addr) {
101 SharingState::Started => {
102 let pos = value.serialize_unsized(self)?;
103 self.finish_sharing(addr, pos)?;
104 Ok(pos)
105 }
106 SharingState::Pending => fail!(CyclicSharedPointerError),
107 SharingState::Finished(pos) => Ok(pos),
108 }
109 }
110}
111
112impl<S, E> SharingExt<E> for S where S: Sharing<E> + ?Sized {}