1use super::codec::{codec_read_type_info_static, codec_ref_mode, codec_write_type_info, Codec};
19use crate::context::{ReadContext, WriteContext};
20use crate::error::Error;
21use crate::meta::FieldType;
22use crate::resolver::{RefMode, TypeInfo, TypeResolver};
23use crate::serializer::Serializer;
24use crate::type_id::TypeId;
25use std::marker::PhantomData;
26use std::rc::Rc;
27use std::sync::{Mutex, MutexGuard};
28
29pub struct MutexCodec<T, C, const NULLABLE: bool, const TRACK_REF: bool>(PhantomData<(T, C)>);
30
31#[inline(always)]
32fn lock_for_write<T>(value: &Mutex<T>) -> Result<MutexGuard<'_, T>, Error> {
33 match value.lock() {
34 Ok(value) => Ok(value),
35 Err(_) => Err(mutex_poison_error()),
36 }
37}
38
39#[inline(always)]
40fn lock_for_inspection<T>(value: &Mutex<T>) -> MutexGuard<'_, T> {
41 match value.lock() {
42 Ok(value) => value,
43 Err(error) => error.into_inner(),
44 }
45}
46
47#[cold]
48#[inline(never)]
49fn mutex_poison_error() -> Error {
50 Error::invalid_data("cannot serialize a poisoned Mutex")
51}
52
53impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Serializer
54 for MutexCodec<T, C, NULLABLE, TRACK_REF>
55where
56 T: 'static,
57 C: Serializer<Target = T>,
58{
59 type Target = Mutex<T>;
60
61 #[inline(always)]
62 fn reserved_space() -> usize {
63 C::reserved_space()
64 }
65
66 #[inline(always)]
67 fn write_data(value: &Mutex<T>, context: &mut WriteContext) -> Result<(), Error> {
68 let value = lock_for_write(value)?;
69 C::write_data(&value, context)
70 }
71
72 #[inline(always)]
73 fn read_data(context: &mut ReadContext) -> Result<Mutex<T>, Error> {
74 Ok(Mutex::new(C::read_data(context)?))
75 }
76
77 #[inline(always)]
78 fn write(
79 value: &Mutex<T>,
80 context: &mut WriteContext,
81 ref_mode: RefMode,
82 write_type_info: bool,
83 ) -> Result<(), Error> {
84 let value = lock_for_write(value)?;
85 C::write(&value, context, ref_mode, write_type_info)
86 }
87
88 #[inline(always)]
89 fn write_type_info_value(
90 context: &mut WriteContext,
91 target_type_id: std::any::TypeId,
92 ) -> Result<Rc<TypeInfo>, Error> {
93 C::write_type_info_value(context, target_type_id)
94 }
95
96 #[inline(always)]
97 fn write_with_type_info(
98 value: &Mutex<T>,
99 context: &mut WriteContext,
100 ref_mode: RefMode,
101 type_info: &Rc<TypeInfo>,
102 ) -> Result<(), Error> {
103 let value = lock_for_write(value)?;
104 C::write_with_type_info(&value, context, ref_mode, type_info)
105 }
106
107 #[inline(always)]
108 fn read(
109 context: &mut ReadContext,
110 ref_mode: RefMode,
111 read_type_info: bool,
112 ) -> Result<Mutex<T>, Error> {
113 Ok(Mutex::new(C::read(context, ref_mode, read_type_info)?))
114 }
115
116 #[inline(always)]
117 fn read_with_type_info(
118 context: &mut ReadContext,
119 ref_mode: RefMode,
120 type_info: &Rc<TypeInfo>,
121 ) -> Result<Mutex<T>, Error> {
122 Ok(Mutex::new(C::read_with_type_info(
123 context, ref_mode, type_info,
124 )?))
125 }
126
127 #[inline(always)]
128 fn default_value(context: &mut ReadContext) -> Result<Mutex<T>, Error> {
129 Ok(Mutex::new(C::default_value(context)?))
130 }
131
132 #[inline(always)]
133 fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
134 C::write_type_info(context)
135 }
136
137 #[inline(always)]
138 fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
139 C::read_type_info(context)
140 }
141
142 #[inline(always)]
143 fn static_type_id() -> TypeId {
144 C::static_type_id()
145 }
146
147 const IS_OPTIONAL: bool = C::IS_OPTIONAL;
148
149 const IS_POLYMORPHIC: bool = C::IS_POLYMORPHIC;
150
151 const IS_SHARED_REF: bool = C::IS_SHARED_REF;
152
153 const IS_WRAPPER: bool = true;
154
155 const REQUIRES_SCOPED_ACCESS: bool = true;
156
157 #[inline(always)]
158 fn is_none(value: &Mutex<T>) -> bool {
159 if !C::IS_OPTIONAL {
160 return false;
161 }
162 C::is_none(&lock_for_inspection(value))
165 }
166
167 #[inline(always)]
168 fn dynamic_type_id(value: &Mutex<T>) -> Result<Option<std::any::TypeId>, Error> {
169 let value = lock_for_write(value)?;
170 C::dynamic_type_id(&value)
171 }
172}
173
174impl<T, C, const NULLABLE: bool, const TRACK_REF: bool> Codec<Mutex<T>>
175 for MutexCodec<T, C, NULLABLE, TRACK_REF>
176where
177 T: 'static,
178 C: Codec<T>,
179{
180 #[inline(always)]
181 fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
182 let mut field_type = C::field_type(type_resolver)?;
183 field_type.nullable = NULLABLE;
184 field_type.track_ref = TRACK_REF;
185 Ok(field_type)
186 }
187
188 #[inline(always)]
189 fn field_reserved_space() -> usize {
190 C::field_reserved_space()
191 }
192
193 #[inline(always)]
194 fn write_field(value: &Mutex<T>, context: &mut WriteContext) -> Result<(), Error> {
195 Self::write_with_mode(
196 value,
197 context,
198 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
199 codec_write_type_info::<T, C>(context),
200 true,
201 )
202 }
203
204 #[inline(always)]
205 fn read_field(context: &mut ReadContext) -> Result<Mutex<T>, Error> {
206 <Self as Serializer>::read(
207 context,
208 codec_ref_mode::<T, C, NULLABLE, TRACK_REF>(),
209 codec_read_type_info_static::<T, C>(context),
210 )
211 }
212
213 #[inline(always)]
214 fn read_data_with_type(
215 context: &mut ReadContext,
216 remote_data_type: &FieldType,
217 ) -> Result<Mutex<T>, Error> {
218 Ok(Mutex::new(C::read_data_with_type(
219 context,
220 remote_data_type,
221 )?))
222 }
223
224 #[inline(always)]
225 fn read_field_with_type(
226 context: &mut ReadContext,
227 remote_field_type: &FieldType,
228 ) -> Result<Mutex<T>, Error> {
229 Ok(Mutex::new(C::read_field_with_type(
230 context,
231 remote_field_type,
232 )?))
233 }
234
235 #[inline(always)]
236 fn write_with_mode(
237 value: &Mutex<T>,
238 context: &mut WriteContext,
239 ref_mode: RefMode,
240 write_type_info: bool,
241 has_generics: bool,
242 ) -> Result<(), Error> {
243 let value = lock_for_write(value)?;
244 C::write_with_mode(&value, context, ref_mode, write_type_info, has_generics)
245 }
246
247 #[inline(always)]
248 fn write_with_type_info(
249 value: &Mutex<T>,
250 context: &mut WriteContext,
251 ref_mode: RefMode,
252 type_info: &Rc<TypeInfo>,
253 has_generics: bool,
254 ) -> Result<(), Error> {
255 let value = lock_for_write(value)?;
256 <C as Codec<T>>::write_with_type_info(&value, context, ref_mode, type_info, has_generics)
257 }
258
259 #[inline(always)]
260 fn read_type_info_value(
261 context: &mut ReadContext,
262 ) -> Result<super::codec::CodecReadType, Error> {
263 C::read_type_info_value(context)
264 }
265}
266
267impl_single_carrier_serializer!(MutexSerializer, Mutex, MutexCodec, wrapper = true);