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