fory_core/serializer/
array.rs1use crate::error::Error;
19use crate::resolver::context::ReadContext;
20use crate::resolver::context::WriteContext;
21use crate::resolver::type_resolver::TypeResolver;
22use crate::serializer::primitive_list;
23use crate::serializer::{ForyDefault, Serializer};
24use crate::types::TypeId;
25use std::mem;
26use std::mem::MaybeUninit;
27
28use super::collection::{
29 read_collection_type_info, write_collection_data, write_collection_type_info,
30 DECL_ELEMENT_TYPE, HAS_NULL, IS_SAME_TYPE,
31};
32use super::list::{get_primitive_type_id, is_primitive_type};
33use crate::ensure;
34use crate::types::{RefFlag, RefMode};
35
36const TRACKING_REF: u8 = 0b1;
38
39#[inline(always)]
41fn validate_array_length(actual: usize, expected: usize) -> Result<(), Error> {
42 if actual != expected {
43 return Err(Error::invalid_data(format!(
44 "Array length mismatch: expected {}, got {}",
45 expected, actual
46 )));
47 }
48 Ok(())
49}
50
51#[inline(always)]
55unsafe fn assume_array_init<T, const N: usize>(arr: &[std::mem::MaybeUninit<T>; N]) -> [T; N] {
56 std::ptr::read(arr as *const _ as *const [T; N])
57}
58
59#[inline]
61fn read_primitive_array<T, const N: usize>(context: &mut ReadContext) -> Result<[T; N], Error>
62where
63 T: Serializer + ForyDefault,
64{
65 let size_bytes = context.reader.read_varuint32()? as usize;
67 let elem_size = mem::size_of::<T>();
68 if size_bytes % elem_size != 0 {
69 return Err(Error::invalid_data("Invalid data length"));
70 }
71 let len = size_bytes / elem_size;
72 validate_array_length(len, N)?;
73 if N == 0 {
75 return Ok(unsafe { std::mem::zeroed() });
77 }
78 let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
80 unsafe {
82 let dst_ptr = arr.as_mut_ptr() as *mut u8;
83 let src = context.reader.read_bytes(size_bytes)?;
84 std::ptr::copy_nonoverlapping(src.as_ptr(), dst_ptr, size_bytes);
85 }
86 Ok(unsafe { assume_array_init(&arr) })
88}
89
90#[inline]
92fn read_complex_array<T, const N: usize>(context: &mut ReadContext) -> Result<[T; N], Error>
93where
94 T: Serializer + ForyDefault,
95{
96 let len = context.reader.read_varuint32()? as usize;
98 validate_array_length(len, N)?;
99 if N == 0 {
101 return Ok(unsafe { std::mem::zeroed() });
103 }
104 if T::fory_is_polymorphic() || T::fory_is_shared_ref() {
106 return read_complex_array_dyn_ref(context, len);
107 }
108 let header = context.reader.read_u8()?;
110 let declared = (header & DECL_ELEMENT_TYPE) != 0;
111 if !declared {
112 T::fory_read_type_info(context)?;
113 }
114 let has_null = (header & HAS_NULL) != 0;
115 ensure!(
116 (header & IS_SAME_TYPE) != 0,
117 Error::type_error("Type inconsistent, target type is not polymorphic")
118 );
119 let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
121 if !has_null {
123 for elem_slot in &mut arr[..] {
124 let elem = T::fory_read_data(context)?;
125 elem_slot.write(elem);
126 }
127 } else {
128 for elem_slot in &mut arr[..] {
129 let flag = context.reader.read_i8()?;
130 let elem = if flag == RefFlag::Null as i8 {
131 T::fory_default()
132 } else {
133 T::fory_read_data(context)?
134 };
135 elem_slot.write(elem);
136 }
137 }
138 Ok(unsafe { std::ptr::read(&arr as *const _ as *const [T; N]) })
140}
141
142#[inline]
144fn read_complex_array_dyn_ref<T, const N: usize>(
145 context: &mut ReadContext,
146 len: usize,
147) -> Result<[T; N], Error>
148where
149 T: Serializer + ForyDefault,
150{
151 let header = context.reader.read_u8()?;
153 let is_track_ref = (header & TRACKING_REF) != 0;
154 let is_same_type = (header & IS_SAME_TYPE) != 0;
155 let has_null = (header & HAS_NULL) != 0;
156 let is_declared = (header & DECL_ELEMENT_TYPE) != 0;
157 let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
159 if is_same_type {
161 let type_info = if !is_declared {
162 context.read_any_type_info()?
163 } else {
164 let rs_type_id = std::any::TypeId::of::<T>();
165 context.get_type_resolver().get_type_info(&rs_type_id)?
166 };
167 if is_track_ref {
168 for elem_slot in arr.iter_mut().take(len) {
169 let elem =
170 T::fory_read_with_type_info(context, RefMode::Tracking, type_info.clone())?;
171 elem_slot.write(elem);
172 }
173 } else if !has_null {
174 for elem_slot in arr.iter_mut().take(len) {
175 let elem = T::fory_read_with_type_info(context, RefMode::None, type_info.clone())?;
176 elem_slot.write(elem);
177 }
178 } else {
179 for elem_slot in arr.iter_mut().take(len) {
180 let flag = context.reader.read_i8()?;
181 let elem = if flag == RefFlag::Null as i8 {
182 T::fory_default()
183 } else {
184 T::fory_read_with_type_info(context, RefMode::None, type_info.clone())?
185 };
186 elem_slot.write(elem);
187 }
188 }
189 } else {
190 let ref_mode = if is_track_ref {
192 RefMode::Tracking
193 } else if has_null {
194 RefMode::NullOnly
195 } else {
196 RefMode::None
197 };
198 for elem_slot in arr.iter_mut().take(len) {
199 let elem = T::fory_read(context, ref_mode, true)?;
200 elem_slot.write(elem);
201 }
202 }
203 Ok(unsafe { std::ptr::read(&arr as *const _ as *const [T; N]) })
205}
206
207impl<T: Serializer + ForyDefault, const N: usize> Serializer for [T; N] {
209 #[inline(always)]
210 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
211 if is_primitive_type::<T>() {
212 primitive_list::fory_write_data(self.as_slice(), context)
213 } else {
214 write_collection_data(self.iter(), context, false)
215 }
216 }
217
218 #[inline(always)]
219 fn fory_write_data_generic(
220 &self,
221 context: &mut WriteContext,
222 has_generics: bool,
223 ) -> Result<(), Error> {
224 if is_primitive_type::<T>() {
225 primitive_list::fory_write_data(self.as_slice(), context)
226 } else {
227 write_collection_data(self.iter(), context, has_generics)
228 }
229 }
230
231 #[inline(always)]
232 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
233 let id = get_primitive_type_id::<T>();
234 if id != TypeId::UNKNOWN {
235 primitive_list::fory_write_type_info(context, id)
236 } else {
237 write_collection_type_info(context, TypeId::LIST as u32)
238 }
239 }
240
241 #[inline(always)]
242 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
243 if is_primitive_type::<T>() {
244 read_primitive_array(context)
246 } else {
247 read_complex_array(context)
249 }
250 }
251
252 #[inline(always)]
253 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
254 let id = get_primitive_type_id::<T>();
255 if id != TypeId::UNKNOWN {
256 primitive_list::fory_read_type_info(context, id)
257 } else {
258 read_collection_type_info(context, TypeId::LIST as u32)
259 }
260 }
261
262 #[inline(always)]
263 fn fory_reserved_space() -> usize {
264 if is_primitive_type::<T>() {
265 primitive_list::fory_reserved_space::<T>()
266 } else {
267 mem::size_of::<u32>()
269 }
270 }
271
272 #[inline(always)]
273 fn fory_static_type_id() -> TypeId
274 where
275 Self: Sized,
276 {
277 let id = get_primitive_type_id::<T>();
278 if id != TypeId::UNKNOWN {
279 id
280 } else {
281 TypeId::LIST
282 }
283 }
284
285 #[inline(always)]
286 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
287 Ok(Self::fory_static_type_id())
288 }
289
290 #[inline(always)]
291 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
292 Ok(Self::fory_static_type_id())
293 }
294
295 #[inline(always)]
296 fn as_any(&self) -> &dyn std::any::Any {
297 self
298 }
299}
300
301impl<T, const N: usize> ForyDefault for [T; N]
302where
303 T: ForyDefault,
304{
305 #[inline(always)]
306 fn fory_default() -> Self {
307 let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
311 for elem in &mut arr {
312 elem.write(T::fory_default());
313 }
314
315 unsafe {
317 std::ptr::read(&arr as *const _ as *const [T; N])
319 }
320 }
321}