1use super::codec::{
19 allows_missing_generics, field_ref_mode, field_types_compatible, generic_field_type, Codec,
20 CodecReadType,
21};
22use super::collection::{
23 write_collection_data, write_collection_value_data, DECL_ELEMENT_TYPE, HAS_NULL, IS_SAME_TYPE,
24 TRACKING_REF,
25};
26use super::primitive_list;
27use crate::context::{ReadContext, WriteContext};
28use crate::error::Error;
29use crate::meta::FieldType;
30use crate::resolver::{RefFlag, RefMode, TypeInfo, TypeResolver};
31use crate::serializer::{core::read_group_type_info, core::read_value_type_info, Serializer};
32use crate::type_id::{TypeId, SIZE_OF_REF_AND_TYPE};
33use std::marker::PhantomData;
34use std::mem::MaybeUninit;
35use std::rc::Rc;
36
37pub struct ArrayCodec<T, C, const N: usize, const NULLABLE: bool, const TRACK_REF: bool>(
38 PhantomData<(T, C)>,
39);
40
41struct ArrayInitGuard<T, const N: usize> {
42 values: [MaybeUninit<T>; N],
43 initialized: usize,
44}
45
46impl<T, const N: usize> ArrayInitGuard<T, N> {
47 #[inline(always)]
48 fn new() -> Self {
49 Self {
50 values: unsafe { MaybeUninit::uninit().assume_init() },
51 initialized: 0,
52 }
53 }
54
55 #[inline(always)]
56 fn push(&mut self, value: T) {
57 self.values[self.initialized].write(value);
58 self.initialized += 1;
59 }
60
61 #[inline(always)]
62 unsafe fn finish(self) -> [T; N] {
63 debug_assert_eq!(self.initialized, N);
64 let result = std::ptr::read(self.values.as_ptr().cast::<[T; N]>());
65 std::mem::forget(self);
66 result
67 }
68}
69
70impl<T, const N: usize> Drop for ArrayInitGuard<T, N> {
71 fn drop(&mut self) {
72 for value in &mut self.values[..self.initialized] {
73 unsafe {
74 value.assume_init_drop();
75 }
76 }
77 }
78}
79
80pub(super) fn try_init_array<T, E, const N: usize>(
81 mut read: impl FnMut() -> Result<T, E>,
82) -> Result<[T; N], E> {
83 let mut values = ArrayInitGuard::<T, N>::new();
84 for _ in 0..N {
85 values.push(read()?);
86 }
87 Ok(unsafe { values.finish() })
88}
89
90#[inline(always)]
91fn selected_array_type_id<T: 'static, S: Serializer<Target = T>>() -> Option<TypeId> {
92 primitive_list::array_type_id::<T, S>(false)
93}
94
95#[cold]
96#[inline(never)]
97fn array_len_mismatch(len: usize, expected: usize) -> Error {
98 Error::invalid_data(format!(
99 "Array length mismatch: expected {expected}, got {len}"
100 ))
101}
102
103#[cold]
104#[inline(never)]
105fn non_polymorphic_array() -> Error {
106 Error::type_error("Type inconsistent, target array element is not polymorphic")
107}
108
109#[cold]
110#[inline(never)]
111fn array_type_mismatch(expected: u32, actual: u32) -> Error {
112 Error::type_mismatch(expected, actual)
113}
114
115#[inline(always)]
116fn check_array_len(len: u32, expected: usize) -> Result<(), Error> {
117 let len = len as usize;
118 if len != expected {
119 return Err(array_len_mismatch(len, expected));
120 }
121 Ok(())
124}
125
126#[inline(always)]
127fn read_declared_items<T, C, const N: usize>(
128 context: &mut ReadContext,
129 element_type: &FieldType,
130 has_null: bool,
131) -> Result<[T; N], Error>
132where
133 T: 'static,
134 C: Codec<T>,
135{
136 try_init_array(|| {
137 if has_null && context.reader.read_i8()? == RefFlag::Null as i8 {
138 C::default_value(context)
139 } else {
140 C::read_data_with_type(context, element_type)
141 }
142 })
143}
144
145#[inline(always)]
146fn read_typed_items<T, C, const N: usize>(
147 context: &mut ReadContext,
148 read_type: &CodecReadType,
149 has_null: bool,
150) -> Result<[T; N], Error>
151where
152 T: 'static,
153 C: Codec<T>,
154{
155 try_init_array(|| {
156 if has_null && context.reader.read_i8()? == RefFlag::Null as i8 {
157 return C::default_value(context);
158 }
159 match read_type {
160 CodecReadType::Field(field_type) => C::read_data_with_type(context, field_type),
161 CodecReadType::TypeInfo(type_info) => C::read_data_with_type_info(context, type_info),
162 }
163 })
164}
165
166macro_rules! array_read_declared_dyn {
167 (value, $T:ty, $S:ty, $N:ident, $context:expr, $remote:expr, $ref_mode:expr, $has_null:expr, $track_ref:expr) => {
168 try_init_array(|| <$S as Serializer>::read($context, $ref_mode, false))
169 };
170 (field, $T:ty, $C:ty, $N:ident, $context:expr, $remote:expr, $ref_mode:expr, $has_null:expr, $track_ref:expr) => {{
171 let element_type = generic_field_type($remote, 0, "array")?;
172 if field_ref_mode(element_type) != $ref_mode {
173 return Err(array_ref_mismatch());
174 }
175 try_init_array(|| <$C as Codec<$T>>::read_field_with_type($context, element_type))
176 }};
177}
178
179macro_rules! array_read_declared {
180 (value, $T:ty, $S:ty, $N:ident, $context:expr, $remote:expr, $has_null:expr) => {
181 try_init_array(|| {
182 if $has_null && $context.reader.read_i8()? == RefFlag::Null as i8 {
183 <$S as Serializer>::default_value($context)
184 } else {
185 <$S as Serializer>::read_data($context)
186 }
187 })
188 };
189 (field, $T:ty, $C:ty, $N:ident, $context:expr, $remote:expr, $has_null:expr) => {{
190 let element_type = generic_field_type($remote, 0, "array")?;
191 read_declared_items::<$T, $C, $N>($context, element_type, $has_null)
192 }};
193}
194
195macro_rules! array_read_typed {
196 (value, $T:ty, $S:ty, $N:ident, $context:expr, $has_null:expr) => {{
197 let type_info = read_value_type_info::<$S, false>($context)?;
198 try_init_array(|| {
199 if $has_null && $context.reader.read_i8()? == RefFlag::Null as i8 {
200 return <$S as Serializer>::default_value($context);
201 }
202 match type_info.as_ref() {
203 Some(type_info) => {
204 <$S as Serializer>::read_with_type_info($context, RefMode::None, type_info)
205 }
206 None => <$S as Serializer>::read_data($context),
207 }
208 })
209 }};
210 (field, $T:ty, $C:ty, $N:ident, $context:expr, $has_null:expr) => {{
211 let read_type = <$C as Codec<$T>>::read_type_info_value($context)?;
212 read_typed_items::<$T, $C, $N>($context, &read_type, $has_null)
213 }};
214}
215
216macro_rules! array_group_type_info {
217 (value, $C:ty, $context:expr) => {
218 read_group_type_info::<$C, false>($context)
219 };
220 (field, $C:ty, $context:expr) => {
221 read_group_type_info::<$C, true>($context)
222 };
223}
224
225macro_rules! read_object_array_body {
226 ($layer:ident, $T:ident, $C:ident, $N:ident, $context:expr, $remote:expr) => {{
227 let context = $context;
228 let len = context.reader.read_var_u32()?;
229 check_array_len(len, $N)?;
230 if $N == 0 {
231 return try_init_array(|| unreachable!());
232 }
233 let header = context.reader.read_u8()?;
234 let track_ref = (header & TRACKING_REF) != 0;
235 let same_type = (header & IS_SAME_TYPE) != 0;
236 let has_null = (header & HAS_NULL) != 0;
237 let declared = (header & DECL_ELEMENT_TYPE) != 0;
238 let ref_mode = if track_ref {
239 RefMode::Tracking
240 } else if has_null {
241 RefMode::NullOnly
242 } else {
243 RefMode::None
244 };
245
246 if $C::IS_POLYMORPHIC || $C::IS_SHARED_REF {
247 if same_type {
248 if declared {
249 return array_read_declared_dyn!(
250 $layer, $T, $C, $N, context, $remote, ref_mode, has_null, track_ref
251 );
252 }
253 let type_info = array_group_type_info!($layer, $C, context)?;
254 return try_init_array(|| {
255 <$C as Serializer>::read_with_type_info(context, ref_mode, &type_info)
256 });
257 }
258 return try_init_array(|| <$C as Serializer>::read(context, ref_mode, true));
259 }
260
261 if !same_type {
262 return Err(non_polymorphic_array());
263 }
264 if declared {
265 return array_read_declared!($layer, $T, $C, $N, context, $remote, has_null);
266 }
267 array_read_typed!($layer, $T, $C, $N, context, has_null)
268 }};
269}
270
271#[inline(always)]
272fn read_value_object_array<T, S, const N: usize>(context: &mut ReadContext) -> Result<[T; N], Error>
273where
274 T: 'static,
275 S: Serializer<Target = T>,
276{
277 read_object_array_body!(value, T, S, N, context, ())
278}
279
280#[inline(always)]
281fn read_field_object_array<T, C, const N: usize>(
282 context: &mut ReadContext,
283 remote_field_type: &FieldType,
284) -> Result<[T; N], Error>
285where
286 T: 'static,
287 C: Codec<T>,
288{
289 read_object_array_body!(field, T, C, N, context, remote_field_type)
290}
291
292#[cold]
293#[inline(never)]
294fn array_ref_mismatch() -> Error {
295 Error::invalid_data("array header conflicts with declared element metadata")
296}
297
298impl<T, S, const N: usize, const NULLABLE: bool, const TRACK_REF: bool> Serializer
299 for ArrayCodec<T, S, N, NULLABLE, TRACK_REF>
300where
301 T: 'static,
302 S: Serializer<Target = T>,
303{
304 type Target = [T; N];
305
306 const READ_DATA_ALWAYS_ADVANCES: bool = true;
307
308 #[inline(always)]
309 fn write_data(value: &Self::Target, context: &mut WriteContext) -> Result<(), Error> {
310 if let Some(type_id) = selected_array_type_id::<T, S>() {
311 return primitive_list::write_data::<T, S>(value, context, type_id);
312 }
313 write_collection_value_data::<T, S, _, false, true>(value.iter(), context)
314 }
315
316 #[inline(always)]
317 fn read_data(context: &mut ReadContext) -> Result<Self::Target, Error> {
318 if let Some(type_id) = selected_array_type_id::<T, S>() {
319 return primitive_list::read_array::<T, S, N>(context, type_id);
320 }
321 read_value_object_array::<T, S, N>(context)
322 }
323
324 #[inline(always)]
325 fn default_value(context: &mut ReadContext) -> Result<Self::Target, Error> {
326 try_init_array(|| S::default_value(context))
327 }
328
329 #[inline(always)]
330 fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
331 match selected_array_type_id::<T, S>() {
332 Some(type_id) => primitive_list::write_type_info(context, type_id),
333 None => {
334 context.writer.write_u8(TypeId::LIST as u8);
335 Ok(())
336 }
337 }
338 }
339
340 #[inline(always)]
341 fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
342 match selected_array_type_id::<T, S>() {
343 Some(type_id) => primitive_list::read_type_info(context, type_id),
344 None => {
345 let remote = context.reader.read_u8()? as u32;
346 if remote != TypeId::LIST as u32 {
347 return Err(array_type_mismatch(TypeId::LIST as u32, remote));
348 }
349 Ok(())
350 }
351 }
352 }
353
354 #[inline(always)]
355 fn static_type_id() -> TypeId {
356 selected_array_type_id::<T, S>().unwrap_or(TypeId::LIST)
357 }
358
359 #[inline(always)]
360 fn reserved_space() -> usize {
361 match selected_array_type_id::<T, S>() {
362 Some(_) => std::mem::size_of::<T>() * N + SIZE_OF_REF_AND_TYPE,
363 None => std::mem::size_of::<u32>() + SIZE_OF_REF_AND_TYPE,
364 }
365 }
366}
367
368impl<T, C, const N: usize, const NULLABLE: bool, const TRACK_REF: bool> Codec<[T; N]>
369 for ArrayCodec<T, C, N, NULLABLE, TRACK_REF>
370where
371 T: 'static,
372 C: Codec<T>,
373{
374 #[inline(always)]
375 fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
376 if let Some(type_id) = selected_array_type_id::<T, C>() {
377 return Ok(FieldType::new_with_ref(
378 type_id as u32,
379 NULLABLE,
380 TRACK_REF,
381 Vec::new(),
382 ));
383 }
384 Ok(FieldType::new_with_ref(
385 TypeId::LIST as u32,
386 NULLABLE,
387 TRACK_REF,
388 vec![C::field_type(type_resolver)?],
389 ))
390 }
391
392 #[inline(always)]
393 fn write_field(value: &[T; N], context: &mut WriteContext) -> Result<(), Error> {
394 if NULLABLE || TRACK_REF {
395 context.writer.write_i8(RefFlag::NotNullValue as i8);
396 }
397 if selected_array_type_id::<T, C>().is_some() {
398 <Self as Serializer>::write_data(value, context)
399 } else {
400 write_collection_data::<T, C, _, false, true>(value.iter(), context, true)
401 }
402 }
403
404 #[inline(always)]
405 fn read_field(context: &mut ReadContext) -> Result<[T; N], Error> {
406 if (NULLABLE || TRACK_REF) && context.reader.read_i8()? == RefFlag::Null as i8 {
407 return <Self as Serializer>::default_value(context);
408 }
409 <Self as Serializer>::read_data(context)
410 }
411
412 #[inline(always)]
413 fn read_compatible(
414 context: &mut ReadContext,
415 local_field_type: &FieldType,
416 remote_field_type: &FieldType,
417 ) -> Result<Option<[T; N]>, Error> {
418 if field_types_compatible(local_field_type, remote_field_type)
419 || local_field_type.compatible_shape_match(remote_field_type)
420 || (local_field_type.type_id == remote_field_type.type_id
421 && allows_missing_generics(local_field_type.type_id)
422 && (local_field_type.generics.is_empty() || remote_field_type.generics.is_empty()))
423 {
424 return Self::read_field_with_type(context, remote_field_type).map(Some);
425 }
426 Ok(None)
427 }
428
429 #[inline(always)]
430 fn read_data_with_type(
431 context: &mut ReadContext,
432 remote_data_type: &FieldType,
433 ) -> Result<[T; N], Error> {
434 if let Some(type_id) = selected_array_type_id::<T, C>() {
435 if remote_data_type.type_id != TypeId::LIST as u32 {
436 return primitive_list::read_array::<T, C, N>(context, type_id);
437 }
438 }
439 read_field_object_array::<T, C, N>(context, remote_data_type)
440 }
441
442 #[inline(always)]
443 fn read_field_with_type(
444 context: &mut ReadContext,
445 remote_field_type: &FieldType,
446 ) -> Result<[T; N], Error> {
447 if field_ref_mode(remote_field_type) != RefMode::None
448 && context.reader.read_i8()? == RefFlag::Null as i8
449 {
450 return <Self as Serializer>::default_value(context);
451 }
452 Self::read_data_with_type(context, remote_field_type)
453 }
454
455 #[inline(always)]
456 fn write_with_mode(
457 value: &[T; N],
458 context: &mut WriteContext,
459 ref_mode: RefMode,
460 write_type_info: bool,
461 has_generics: bool,
462 ) -> Result<(), Error> {
463 if selected_array_type_id::<T, C>().is_some() || !has_generics {
464 return <Self as Serializer>::write(value, context, ref_mode, write_type_info);
465 }
466 if ref_mode != RefMode::None {
467 context.writer.write_i8(RefFlag::NotNullValue as i8);
468 }
469 if write_type_info {
470 <Self as Serializer>::write_type_info(context)?;
471 }
472 write_collection_data::<T, C, _, false, true>(value.iter(), context, true)
473 }
474}
475
476type RootArrayCodec<S, const N: usize> = ArrayCodec<<S as Serializer>::Target, S, N, false, false>;
477
478pub struct ArraySerializer<S, const N: usize>(PhantomData<fn() -> S>);
483
484impl<S: Serializer, const N: usize> Serializer for ArraySerializer<S, N> {
485 type Target = [S::Target; N];
486
487 const READ_DATA_ALWAYS_ADVANCES: bool = true;
488
489 #[inline(always)]
490 fn write_data(value: &Self::Target, context: &mut WriteContext) -> Result<(), Error> {
491 <RootArrayCodec<S, N> as Serializer>::write_data(value, context)
492 }
493
494 #[inline(always)]
495 fn read_data(context: &mut ReadContext) -> Result<Self::Target, Error> {
496 <RootArrayCodec<S, N> as Serializer>::read_data(context)
497 }
498
499 #[inline(always)]
500 fn default_value(context: &mut ReadContext) -> Result<Self::Target, Error> {
501 <RootArrayCodec<S, N> as Serializer>::default_value(context)
502 }
503
504 #[inline(always)]
505 fn write(
506 value: &Self::Target,
507 context: &mut WriteContext,
508 ref_mode: RefMode,
509 write_type_info: bool,
510 ) -> Result<(), Error> {
511 <RootArrayCodec<S, N> as Serializer>::write(value, context, ref_mode, write_type_info)
512 }
513
514 #[inline(always)]
515 fn read(
516 context: &mut ReadContext,
517 ref_mode: RefMode,
518 read_type_info: bool,
519 ) -> Result<Self::Target, Error> {
520 <RootArrayCodec<S, N> as Serializer>::read(context, ref_mode, read_type_info)
521 }
522
523 #[inline(always)]
524 fn read_with_type_info(
525 context: &mut ReadContext,
526 ref_mode: RefMode,
527 type_info: &Rc<TypeInfo>,
528 ) -> Result<Self::Target, Error> {
529 <RootArrayCodec<S, N> as Serializer>::read_with_type_info(context, ref_mode, type_info)
530 }
531
532 #[inline(always)]
533 fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
534 <RootArrayCodec<S, N> as Serializer>::write_type_info(context)
535 }
536
537 #[inline(always)]
538 fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
539 <RootArrayCodec<S, N> as Serializer>::read_type_info(context)
540 }
541
542 #[inline(always)]
543 fn static_type_id() -> TypeId {
544 <RootArrayCodec<S, N> as Serializer>::static_type_id()
545 }
546
547 #[inline(always)]
548 fn reserved_space() -> usize {
549 <RootArrayCodec<S, N> as Serializer>::reserved_space()
550 }
551}
552
553impl<T, const N: usize> Serializer for [T; N]
554where
555 T: Serializer<Target = T>,
556{
557 type Target = Self;
558
559 const READ_DATA_ALWAYS_ADVANCES: bool = true;
560
561 #[inline(always)]
562 fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
563 <ArraySerializer<T, N> as Serializer>::write_data(value, context)
564 }
565
566 #[inline(always)]
567 fn read_data(context: &mut ReadContext) -> Result<Self, Error> {
568 <ArraySerializer<T, N> as Serializer>::read_data(context)
569 }
570
571 #[inline(always)]
572 fn default_value(context: &mut ReadContext) -> Result<Self, Error> {
573 <ArraySerializer<T, N> as Serializer>::default_value(context)
574 }
575
576 #[inline(always)]
577 fn write(
578 value: &Self,
579 context: &mut WriteContext,
580 ref_mode: RefMode,
581 write_type_info: bool,
582 ) -> Result<(), Error> {
583 <ArraySerializer<T, N> as Serializer>::write(value, context, ref_mode, write_type_info)
584 }
585
586 #[inline(always)]
587 fn read(
588 context: &mut ReadContext,
589 ref_mode: RefMode,
590 read_type_info: bool,
591 ) -> Result<Self, Error> {
592 <ArraySerializer<T, N> as Serializer>::read(context, ref_mode, read_type_info)
593 }
594
595 #[inline(always)]
596 fn read_with_type_info(
597 context: &mut ReadContext,
598 ref_mode: RefMode,
599 type_info: &Rc<TypeInfo>,
600 ) -> Result<Self, Error> {
601 <ArraySerializer<T, N> as Serializer>::read_with_type_info(context, ref_mode, type_info)
602 }
603
604 #[inline(always)]
605 fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
606 <ArraySerializer<T, N> as Serializer>::write_type_info(context)
607 }
608
609 #[inline(always)]
610 fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
611 <ArraySerializer<T, N> as Serializer>::read_type_info(context)
612 }
613
614 #[inline(always)]
615 fn static_type_id() -> TypeId {
616 <ArraySerializer<T, N> as Serializer>::static_type_id()
617 }
618
619 #[inline(always)]
620 fn reserved_space() -> usize {
621 <ArraySerializer<T, N> as Serializer>::reserved_space()
622 }
623}