1use shape_value::NativeKind;
35use shape_value::heap_value::TypedObjectStorage;
36use shape_value::v2::decimal_obj::DecimalObj;
37use shape_value::v2::heap_element::HeapElement;
38use shape_value::v2::heap_header::{HEAP_KIND_V2_TYPED_ARRAY, HeapHeader};
39use shape_value::v2::refcount::v2_retain;
40use shape_value::v2::string_obj::StringObj;
41use shape_value::v2::typed_array::TypedArray;
42use shape_value::HeapKind;
43
44pub use shape_value::v2::typed_array::{
60 ELEM_TYPE_BOOL, ELEM_TYPE_CHAR, ELEM_TYPE_DECIMAL, ELEM_TYPE_F32, ELEM_TYPE_F64,
61 ELEM_TYPE_I16, ELEM_TYPE_I32, ELEM_TYPE_I64, ELEM_TYPE_I8, ELEM_TYPE_STRING,
62 ELEM_TYPE_TYPED_OBJECT, ELEM_TYPE_U16, ELEM_TYPE_U32, ELEM_TYPE_U8, ELEM_TYPE_UNKNOWN,
63};
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum V2ElemType {
67 F64,
68 I64,
69 I32,
70 Bool,
71 I8,
73 U8,
74 I16,
75 U16,
76 U32,
77 F32,
80 Char,
81 String,
87 Decimal,
88 TypedObject,
93}
94
95impl V2ElemType {
96 #[inline]
97 pub fn from_byte(b: u8) -> Option<Self> {
98 match b {
99 ELEM_TYPE_F64 => Some(V2ElemType::F64),
100 ELEM_TYPE_I64 => Some(V2ElemType::I64),
101 ELEM_TYPE_I32 => Some(V2ElemType::I32),
102 ELEM_TYPE_BOOL => Some(V2ElemType::Bool),
103 ELEM_TYPE_I8 => Some(V2ElemType::I8),
104 ELEM_TYPE_U8 => Some(V2ElemType::U8),
105 ELEM_TYPE_I16 => Some(V2ElemType::I16),
106 ELEM_TYPE_U16 => Some(V2ElemType::U16),
107 ELEM_TYPE_U32 => Some(V2ElemType::U32),
108 ELEM_TYPE_F32 => Some(V2ElemType::F32),
111 ELEM_TYPE_CHAR => Some(V2ElemType::Char),
112 ELEM_TYPE_STRING => Some(V2ElemType::String),
113 ELEM_TYPE_DECIMAL => Some(V2ElemType::Decimal),
114 ELEM_TYPE_TYPED_OBJECT => Some(V2ElemType::TypedObject),
116 _ => None,
117 }
118 }
119
120 #[inline]
123 pub fn elem_kind(self) -> NativeKind {
124 match self {
125 V2ElemType::F64 => NativeKind::Float64,
126 V2ElemType::I64 => NativeKind::Int64,
127 V2ElemType::I32 => NativeKind::Int32,
128 V2ElemType::Bool => NativeKind::Bool,
129 V2ElemType::I8 => NativeKind::Int8,
130 V2ElemType::U8 => NativeKind::UInt8,
131 V2ElemType::I16 => NativeKind::Int16,
132 V2ElemType::U16 => NativeKind::UInt16,
133 V2ElemType::U32 => NativeKind::UInt32,
134 V2ElemType::F32 => NativeKind::Float32,
135 V2ElemType::Char => NativeKind::Char,
136 V2ElemType::String => NativeKind::StringV2,
137 V2ElemType::Decimal => NativeKind::DecimalV2,
138 V2ElemType::TypedObject => {
141 NativeKind::Ptr(shape_value::HeapKind::TypedObject)
142 }
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy)]
150pub struct V2TypedArrayView {
151 pub ptr: *mut u8,
152 pub elem_type: V2ElemType,
153 pub len: u32,
154}
155
156#[inline]
159pub unsafe fn stamp_elem_type(ptr: *mut u8, elem_type: u8) {
160 if ptr.is_null() {
161 return;
162 }
163 unsafe {
164 let pad = ptr.add(7);
165 *pad = elem_type;
166 }
167}
168
169#[inline]
171unsafe fn read_elem_type_byte(ptr: *const u8) -> u8 {
172 if ptr.is_null() {
173 return ELEM_TYPE_UNKNOWN;
174 }
175 unsafe { *ptr.add(7) }
176}
177
178#[inline]
207pub fn as_v2_typed_array(bits: u64, kind: NativeKind) -> Option<V2TypedArrayView> {
208 if !matches!(kind, NativeKind::Ptr(HeapKind::TypedArray)) {
209 return None;
210 }
211 if bits == 0 {
212 return None;
213 }
214 let ptr = bits as usize as *mut u8;
215 let header = unsafe { &*(ptr as *const HeapHeader) };
216 if header.kind != HEAP_KIND_V2_TYPED_ARRAY {
217 return None;
218 }
219 let elem_byte = unsafe { read_elem_type_byte(ptr) };
220 let elem_type = V2ElemType::from_byte(elem_byte)?;
221 let arr_u8 = ptr as *const TypedArray<u8>;
222 let len = unsafe { (*arr_u8).len };
223 Some(V2TypedArrayView {
224 ptr,
225 elem_type,
226 len,
227 })
228}
229
230#[inline]
235fn decode_f64(bits: u64, kind: NativeKind) -> Option<f64> {
236 if matches!(kind, NativeKind::Float64 | NativeKind::NullableFloat64) {
237 return Some(f64::from_bits(bits));
238 }
239 if kind.is_integer_family() {
240 return Some(decode_i64(bits, kind)? as f64);
241 }
242 None
243}
244
245#[inline]
249fn decode_i64(bits: u64, kind: NativeKind) -> Option<i64> {
250 match kind {
251 NativeKind::Int64 | NativeKind::NullableInt64 => Some(bits as i64),
252 NativeKind::Int32 | NativeKind::NullableInt32 => Some(bits as u32 as i32 as i64),
253 NativeKind::Int16 | NativeKind::NullableInt16 => Some(bits as u16 as i16 as i64),
254 NativeKind::Int8 | NativeKind::NullableInt8 => Some(bits as u8 as i8 as i64),
255 NativeKind::IntSize | NativeKind::NullableIntSize => Some(bits as isize as i64),
256 NativeKind::UInt64 | NativeKind::NullableUInt64 => Some(bits as i64),
257 NativeKind::UInt32 | NativeKind::NullableUInt32 => Some(bits as u32 as i64),
258 NativeKind::UInt16 | NativeKind::NullableUInt16 => Some(bits as u16 as i64),
259 NativeKind::UInt8 | NativeKind::NullableUInt8 => Some(bits as u8 as i64),
260 NativeKind::UIntSize | NativeKind::NullableUIntSize => Some(bits as usize as i64),
261 NativeKind::Float64 | NativeKind::NullableFloat64 => Some(f64::from_bits(bits) as i64),
262 _ => None,
263 }
264}
265
266#[inline]
268fn decode_bool(bits: u64, kind: NativeKind) -> Option<bool> {
269 if matches!(kind, NativeKind::Bool) {
270 Some(bits != 0)
271 } else {
272 None
273 }
274}
275
276#[inline]
280fn decode_f32(bits: u64, kind: NativeKind) -> Option<f32> {
281 if matches!(kind, NativeKind::Float32) {
282 return Some(f32::from_bits(bits as u32));
283 }
284 if let Some(v) = decode_f64(bits, kind) {
285 return Some(v as f32);
286 }
287 None
288}
289
290#[inline]
296fn decode_char(bits: u64, kind: NativeKind) -> Option<char> {
297 if matches!(kind, NativeKind::Char) {
298 return char::from_u32(bits as u32);
299 }
300 if kind.is_integer_family() {
301 let cp = decode_i64(bits, kind)?;
302 if cp < 0 {
303 return None;
304 }
305 return char::from_u32(cp as u32);
306 }
307 None
308}
309
310#[inline]
316pub fn read_element(view: &V2TypedArrayView, index: u32) -> Option<(u64, NativeKind)> {
317 if index >= view.len {
318 return None;
319 }
320 let pair = match view.elem_type {
321 V2ElemType::F64 => unsafe {
322 let arr = view.ptr as *const TypedArray<f64>;
323 let v = TypedArray::<f64>::get_unchecked(arr, index);
324 (v.to_bits(), NativeKind::Float64)
325 },
326 V2ElemType::I64 => unsafe {
327 let arr = view.ptr as *const TypedArray<i64>;
328 let v = TypedArray::<i64>::get_unchecked(arr, index);
329 (v as u64, NativeKind::Int64)
330 },
331 V2ElemType::I32 => unsafe {
332 let arr = view.ptr as *const TypedArray<i32>;
333 let v = TypedArray::<i32>::get_unchecked(arr, index) as i64;
334 (v as u64, NativeKind::Int32)
335 },
336 V2ElemType::Bool => unsafe {
337 let arr = view.ptr as *const TypedArray<u8>;
338 let v = TypedArray::<u8>::get_unchecked(arr, index) != 0;
339 (v as u64, NativeKind::Bool)
340 },
341 V2ElemType::I8 => unsafe {
343 let arr = view.ptr as *const TypedArray<i8>;
344 let v = TypedArray::<i8>::get_unchecked(arr, index) as i64;
345 (v as u64, NativeKind::Int8)
346 },
347 V2ElemType::U8 => unsafe {
348 let arr = view.ptr as *const TypedArray<u8>;
349 let v = TypedArray::<u8>::get_unchecked(arr, index) as u64;
350 (v, NativeKind::UInt8)
351 },
352 V2ElemType::I16 => unsafe {
353 let arr = view.ptr as *const TypedArray<i16>;
354 let v = TypedArray::<i16>::get_unchecked(arr, index) as i64;
355 (v as u64, NativeKind::Int16)
356 },
357 V2ElemType::U16 => unsafe {
358 let arr = view.ptr as *const TypedArray<u16>;
359 let v = TypedArray::<u16>::get_unchecked(arr, index) as u64;
360 (v, NativeKind::UInt16)
361 },
362 V2ElemType::U32 => unsafe {
363 let arr = view.ptr as *const TypedArray<u32>;
364 let v = TypedArray::<u32>::get_unchecked(arr, index) as u64;
365 (v, NativeKind::UInt32)
366 },
367 V2ElemType::F32 => unsafe {
369 let arr = view.ptr as *const TypedArray<f32>;
370 let v = TypedArray::<f32>::get_unchecked(arr, index);
371 (v.to_bits() as u64, NativeKind::Float32)
372 },
373 V2ElemType::Char => unsafe {
374 let arr = view.ptr as *const TypedArray<char>;
375 let v = TypedArray::<char>::get_unchecked(arr, index);
376 (v as u32 as u64, NativeKind::Char)
377 },
378 V2ElemType::String => unsafe {
385 let arr = view.ptr as *const TypedArray<*const StringObj>;
386 let elem_ptr = TypedArray::<*const StringObj>::get_unchecked(arr, index);
387 v2_retain(&(*elem_ptr).header);
388 (elem_ptr as u64, NativeKind::StringV2)
389 },
390 V2ElemType::Decimal => unsafe {
391 let arr = view.ptr as *const TypedArray<*const DecimalObj>;
392 let elem_ptr = TypedArray::<*const DecimalObj>::get_unchecked(arr, index);
393 v2_retain(&(*elem_ptr).header);
394 (elem_ptr as u64, NativeKind::DecimalV2)
395 },
396 V2ElemType::TypedObject => unsafe {
404 let arr = view.ptr as *const TypedArray<*const TypedObjectStorage>;
405 let elem_ptr =
406 TypedArray::<*const TypedObjectStorage>::get_unchecked(arr, index);
407 v2_retain(&(*elem_ptr).header);
408 (elem_ptr as u64, NativeKind::Ptr(HeapKind::TypedObject))
409 },
410 };
411 Some(pair)
412}
413
414#[inline]
416pub fn write_element(
417 view: &V2TypedArrayView,
418 index: u32,
419 bits: u64,
420 kind: NativeKind,
421) -> Result<(), &'static str> {
422 if index >= view.len {
423 return Err("index out of bounds");
424 }
425 match view.elem_type {
426 V2ElemType::F64 => {
427 let v = decode_f64(bits, kind).ok_or("expected f64-compatible value")?;
428 unsafe {
429 let arr = view.ptr as *mut TypedArray<f64>;
430 TypedArray::<f64>::set(arr, index, v);
431 }
432 }
433 V2ElemType::I64 => {
434 let v = decode_i64(bits, kind).ok_or("expected i64-compatible value")?;
435 unsafe {
436 let arr = view.ptr as *mut TypedArray<i64>;
437 TypedArray::<i64>::set(arr, index, v);
438 }
439 }
440 V2ElemType::I32 => {
441 let v = decode_i64(bits, kind).ok_or("expected i32-compatible value")?;
442 unsafe {
443 let arr = view.ptr as *mut TypedArray<i32>;
444 TypedArray::<i32>::set(arr, index, v as i32);
445 }
446 }
447 V2ElemType::Bool => {
448 let v = decode_bool(bits, kind).ok_or("expected bool value")?;
449 unsafe {
450 let arr = view.ptr as *mut TypedArray<u8>;
451 TypedArray::<u8>::set(arr, index, if v { 1 } else { 0 });
452 }
453 }
454 V2ElemType::I8 => {
456 let v = decode_i64(bits, kind).ok_or("expected i8-compatible value")?;
457 unsafe {
458 let arr = view.ptr as *mut TypedArray<i8>;
459 TypedArray::<i8>::set(arr, index, v as i8);
460 }
461 }
462 V2ElemType::U8 => {
463 let v = decode_i64(bits, kind).ok_or("expected u8-compatible value")?;
464 unsafe {
465 let arr = view.ptr as *mut TypedArray<u8>;
466 TypedArray::<u8>::set(arr, index, v as u8);
467 }
468 }
469 V2ElemType::I16 => {
470 let v = decode_i64(bits, kind).ok_or("expected i16-compatible value")?;
471 unsafe {
472 let arr = view.ptr as *mut TypedArray<i16>;
473 TypedArray::<i16>::set(arr, index, v as i16);
474 }
475 }
476 V2ElemType::U16 => {
477 let v = decode_i64(bits, kind).ok_or("expected u16-compatible value")?;
478 unsafe {
479 let arr = view.ptr as *mut TypedArray<u16>;
480 TypedArray::<u16>::set(arr, index, v as u16);
481 }
482 }
483 V2ElemType::U32 => {
484 let v = decode_i64(bits, kind).ok_or("expected u32-compatible value")?;
485 unsafe {
486 let arr = view.ptr as *mut TypedArray<u32>;
487 TypedArray::<u32>::set(arr, index, v as u32);
488 }
489 }
490 V2ElemType::F32 => {
492 let v = decode_f32(bits, kind).ok_or("expected f32-compatible value")?;
493 unsafe {
494 let arr = view.ptr as *mut TypedArray<f32>;
495 TypedArray::<f32>::set(arr, index, v);
496 }
497 }
498 V2ElemType::Char => {
499 let v = decode_char(bits, kind).ok_or("expected char-compatible value")?;
500 unsafe {
501 let arr = view.ptr as *mut TypedArray<char>;
502 TypedArray::<char>::set(arr, index, v);
503 }
504 }
505 V2ElemType::String => {
514 if kind != NativeKind::StringV2 {
515 return Err("expected NativeKind::StringV2 for Array<string> write");
516 }
517 let new_ptr = bits as usize as *const StringObj;
518 unsafe {
519 let arr = view.ptr as *mut TypedArray<*const StringObj>;
520 let old_ptr = TypedArray::<*const StringObj>::get_unchecked(arr, index);
521 <StringObj as HeapElement>::release_elem(old_ptr);
522 TypedArray::<*const StringObj>::set(arr, index, new_ptr);
523 }
524 }
525 V2ElemType::Decimal => {
526 if kind != NativeKind::DecimalV2 {
527 return Err("expected NativeKind::DecimalV2 for Array<decimal> write");
528 }
529 let new_ptr = bits as usize as *const DecimalObj;
530 unsafe {
531 let arr = view.ptr as *mut TypedArray<*const DecimalObj>;
532 let old_ptr = TypedArray::<*const DecimalObj>::get_unchecked(arr, index);
533 <DecimalObj as HeapElement>::release_elem(old_ptr);
534 TypedArray::<*const DecimalObj>::set(arr, index, new_ptr);
535 }
536 }
537 V2ElemType::TypedObject => {
542 if kind != NativeKind::Ptr(HeapKind::TypedObject) {
543 return Err(
544 "expected NativeKind::Ptr(HeapKind::TypedObject) for Array<TypedObject> write",
545 );
546 }
547 let new_ptr = bits as usize as *const TypedObjectStorage;
548 unsafe {
549 let arr = view.ptr as *mut TypedArray<*const TypedObjectStorage>;
550 let old_ptr =
551 TypedArray::<*const TypedObjectStorage>::get_unchecked(arr, index);
552 <TypedObjectStorage as HeapElement>::release_elem(old_ptr);
553 TypedArray::<*const TypedObjectStorage>::set(arr, index, new_ptr);
554 }
555 }
556 }
557 Ok(())
558}
559
560#[inline]
562pub fn push_element(
563 view: &V2TypedArrayView,
564 bits: u64,
565 kind: NativeKind,
566) -> Result<(), &'static str> {
567 match view.elem_type {
568 V2ElemType::F64 => {
569 let v = decode_f64(bits, kind).ok_or("expected f64-compatible value")?;
570 unsafe {
571 let arr = view.ptr as *mut TypedArray<f64>;
572 TypedArray::<f64>::push(arr, v);
573 }
574 }
575 V2ElemType::I64 => {
576 let v = decode_i64(bits, kind).ok_or("expected i64-compatible value")?;
577 unsafe {
578 let arr = view.ptr as *mut TypedArray<i64>;
579 TypedArray::<i64>::push(arr, v);
580 }
581 }
582 V2ElemType::I32 => {
583 let v = decode_i64(bits, kind).ok_or("expected i32-compatible value")?;
584 unsafe {
585 let arr = view.ptr as *mut TypedArray<i32>;
586 TypedArray::<i32>::push(arr, v as i32);
587 }
588 }
589 V2ElemType::Bool => {
590 let v = decode_bool(bits, kind).ok_or("expected bool value")?;
591 unsafe {
592 let arr = view.ptr as *mut TypedArray<u8>;
593 TypedArray::<u8>::push(arr, if v { 1 } else { 0 });
594 }
595 }
596 V2ElemType::I8 => {
598 let v = decode_i64(bits, kind).ok_or("expected i8-compatible value")?;
599 unsafe {
600 let arr = view.ptr as *mut TypedArray<i8>;
601 TypedArray::<i8>::push(arr, v as i8);
602 }
603 }
604 V2ElemType::U8 => {
605 let v = decode_i64(bits, kind).ok_or("expected u8-compatible value")?;
606 unsafe {
607 let arr = view.ptr as *mut TypedArray<u8>;
608 TypedArray::<u8>::push(arr, v as u8);
609 }
610 }
611 V2ElemType::I16 => {
612 let v = decode_i64(bits, kind).ok_or("expected i16-compatible value")?;
613 unsafe {
614 let arr = view.ptr as *mut TypedArray<i16>;
615 TypedArray::<i16>::push(arr, v as i16);
616 }
617 }
618 V2ElemType::U16 => {
619 let v = decode_i64(bits, kind).ok_or("expected u16-compatible value")?;
620 unsafe {
621 let arr = view.ptr as *mut TypedArray<u16>;
622 TypedArray::<u16>::push(arr, v as u16);
623 }
624 }
625 V2ElemType::U32 => {
626 let v = decode_i64(bits, kind).ok_or("expected u32-compatible value")?;
627 unsafe {
628 let arr = view.ptr as *mut TypedArray<u32>;
629 TypedArray::<u32>::push(arr, v as u32);
630 }
631 }
632 V2ElemType::F32 => {
634 let v = decode_f32(bits, kind).ok_or("expected f32-compatible value")?;
635 unsafe {
636 let arr = view.ptr as *mut TypedArray<f32>;
637 TypedArray::<f32>::push(arr, v);
638 }
639 }
640 V2ElemType::Char => {
641 let v = decode_char(bits, kind).ok_or("expected char-compatible value")?;
642 unsafe {
643 let arr = view.ptr as *mut TypedArray<char>;
644 TypedArray::<char>::push(arr, v);
645 }
646 }
647 V2ElemType::String => {
653 if kind != NativeKind::StringV2 {
654 return Err("expected NativeKind::StringV2 for Array<string> push");
655 }
656 let new_ptr = bits as usize as *const StringObj;
657 unsafe {
658 let arr = view.ptr as *mut TypedArray<*const StringObj>;
659 TypedArray::<*const StringObj>::push(arr, new_ptr);
660 }
661 }
662 V2ElemType::Decimal => {
663 if kind != NativeKind::DecimalV2 {
664 return Err("expected NativeKind::DecimalV2 for Array<decimal> push");
665 }
666 let new_ptr = bits as usize as *const DecimalObj;
667 unsafe {
668 let arr = view.ptr as *mut TypedArray<*const DecimalObj>;
669 TypedArray::<*const DecimalObj>::push(arr, new_ptr);
670 }
671 }
672 V2ElemType::TypedObject => {
674 if kind != NativeKind::Ptr(HeapKind::TypedObject) {
675 return Err(
676 "expected NativeKind::Ptr(HeapKind::TypedObject) for Array<TypedObject> push",
677 );
678 }
679 let new_ptr = bits as usize as *const TypedObjectStorage;
680 unsafe {
681 let arr = view.ptr as *mut TypedArray<*const TypedObjectStorage>;
682 TypedArray::<*const TypedObjectStorage>::push(arr, new_ptr);
683 }
684 }
685 }
686 Ok(())
687}
688
689#[inline]
691pub fn pop_element(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
692 match view.elem_type {
693 V2ElemType::F64 => unsafe {
694 let arr = view.ptr as *mut TypedArray<f64>;
695 TypedArray::<f64>::pop(arr).map(|v| (v.to_bits(), NativeKind::Float64))
696 },
697 V2ElemType::I64 => unsafe {
698 let arr = view.ptr as *mut TypedArray<i64>;
699 TypedArray::<i64>::pop(arr).map(|v| (v as u64, NativeKind::Int64))
700 },
701 V2ElemType::I32 => unsafe {
702 let arr = view.ptr as *mut TypedArray<i32>;
703 TypedArray::<i32>::pop(arr).map(|v| (v as i64 as u64, NativeKind::Int32))
704 },
705 V2ElemType::Bool => unsafe {
706 let arr = view.ptr as *mut TypedArray<u8>;
707 TypedArray::<u8>::pop(arr).map(|v| ((v != 0) as u64, NativeKind::Bool))
708 },
709 V2ElemType::I8 => unsafe {
711 let arr = view.ptr as *mut TypedArray<i8>;
712 TypedArray::<i8>::pop(arr).map(|v| (v as i64 as u64, NativeKind::Int8))
713 },
714 V2ElemType::U8 => unsafe {
715 let arr = view.ptr as *mut TypedArray<u8>;
716 TypedArray::<u8>::pop(arr).map(|v| (v as u64, NativeKind::UInt8))
717 },
718 V2ElemType::I16 => unsafe {
719 let arr = view.ptr as *mut TypedArray<i16>;
720 TypedArray::<i16>::pop(arr).map(|v| (v as i64 as u64, NativeKind::Int16))
721 },
722 V2ElemType::U16 => unsafe {
723 let arr = view.ptr as *mut TypedArray<u16>;
724 TypedArray::<u16>::pop(arr).map(|v| (v as u64, NativeKind::UInt16))
725 },
726 V2ElemType::U32 => unsafe {
727 let arr = view.ptr as *mut TypedArray<u32>;
728 TypedArray::<u32>::pop(arr).map(|v| (v as u64, NativeKind::UInt32))
729 },
730 V2ElemType::F32 => unsafe {
732 let arr = view.ptr as *mut TypedArray<f32>;
733 TypedArray::<f32>::pop(arr).map(|v| (v.to_bits() as u64, NativeKind::Float32))
734 },
735 V2ElemType::Char => unsafe {
736 let arr = view.ptr as *mut TypedArray<char>;
737 TypedArray::<char>::pop(arr).map(|v| (v as u32 as u64, NativeKind::Char))
738 },
739 V2ElemType::String => unsafe {
744 let arr = view.ptr as *mut TypedArray<*const StringObj>;
745 TypedArray::<*const StringObj>::pop(arr).map(|v| (v as u64, NativeKind::StringV2))
746 },
747 V2ElemType::Decimal => unsafe {
748 let arr = view.ptr as *mut TypedArray<*const DecimalObj>;
749 TypedArray::<*const DecimalObj>::pop(arr).map(|v| (v as u64, NativeKind::DecimalV2))
750 },
751 V2ElemType::TypedObject => unsafe {
755 let arr = view.ptr as *mut TypedArray<*const TypedObjectStorage>;
756 TypedArray::<*const TypedObjectStorage>::pop(arr)
757 .map(|v| (v as u64, NativeKind::Ptr(HeapKind::TypedObject)))
758 },
759 }
760}
761
762pub fn sum_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
772 const SIMD_SUM_THRESHOLD: u32 = 16;
775
776 match view.elem_type {
777 V2ElemType::F64 => {
778 let len = view.len;
779 if len == 0 {
780 return Some((0.0_f64.to_bits(), NativeKind::Float64));
781 }
782 let data = unsafe {
783 let arr = view.ptr as *const TypedArray<f64>;
784 (*arr).data as *const f64
785 };
786 let s = unsafe { simd_sum_f64(data, len as usize, SIMD_SUM_THRESHOLD as usize) };
787 Some((s.to_bits(), NativeKind::Float64))
788 }
789 V2ElemType::I64 => {
790 let len = view.len;
791 if len == 0 {
792 return Some((0u64, NativeKind::Int64));
793 }
794 let data = unsafe {
795 let arr = view.ptr as *const TypedArray<i64>;
796 (*arr).data as *const i64
797 };
798 let s = unsafe { simd_sum_i64(data, len as usize, SIMD_SUM_THRESHOLD as usize) };
799 Some((s as u64, NativeKind::Int64))
800 }
801 V2ElemType::I32 => {
802 let mut s: i64 = 0;
803 for i in 0..view.len {
804 let val = unsafe {
805 let arr = view.ptr as *const TypedArray<i32>;
806 TypedArray::<i32>::get_unchecked(arr, i) as i64
807 };
808 s = s.wrapping_add(val);
809 }
810 Some((s as u64, NativeKind::Int64))
811 }
812 V2ElemType::Bool
818 | V2ElemType::I8
819 | V2ElemType::U8
820 | V2ElemType::I16
821 | V2ElemType::U16
822 | V2ElemType::U32
823 | V2ElemType::F32
824 | V2ElemType::Char
825 | V2ElemType::String
829 | V2ElemType::Decimal
830 | V2ElemType::TypedObject => None,
831 }
832}
833
834#[inline]
839unsafe fn simd_sum_f64(data: *const f64, len: usize, threshold: usize) -> f64 {
840 use wide::f64x4;
841
842 if len < threshold {
843 let mut s = 0.0_f64;
844 for i in 0..len {
845 s += unsafe { *data.add(i) };
846 }
847 return s;
848 }
849
850 let chunks = len / 4;
851 let mut acc = f64x4::splat(0.0);
852 for i in 0..chunks {
853 let base = i * 4;
854 let v = unsafe {
855 f64x4::from([
856 *data.add(base),
857 *data.add(base + 1),
858 *data.add(base + 2),
859 *data.add(base + 3),
860 ])
861 };
862 acc += v;
863 }
864 let parts = acc.to_array();
865 let mut s = parts[0] + parts[1] + parts[2] + parts[3];
866 for i in (chunks * 4)..len {
867 s += unsafe { *data.add(i) };
868 }
869 s
870}
871
872#[inline]
878unsafe fn contains_nan_f64(data: *const f64, len: usize) -> bool {
879 for i in 0..len {
880 if unsafe { *data.add(i) }.is_nan() {
881 return true;
882 }
883 }
884 false
885}
886
887#[inline]
897unsafe fn simd_min_f64(data: *const f64, len: usize, threshold: usize) -> f64 {
898 use wide::f64x4;
899 debug_assert!(len > 0);
900 if unsafe { contains_nan_f64(data, len) } {
901 return f64::NAN;
902 }
903 if len < threshold {
904 let mut m = unsafe { *data };
905 for i in 1..len {
906 let v = unsafe { *data.add(i) };
907 if v < m {
908 m = v;
909 }
910 }
911 return m;
912 }
913 let chunks = len / 4;
914 let mut acc = unsafe {
915 f64x4::from([
916 *data,
917 *data.add(1),
918 *data.add(2),
919 *data.add(3),
920 ])
921 };
922 for i in 1..chunks {
923 let base = i * 4;
924 let v = unsafe {
925 f64x4::from([
926 *data.add(base),
927 *data.add(base + 1),
928 *data.add(base + 2),
929 *data.add(base + 3),
930 ])
931 };
932 acc = acc.fast_min(v);
933 }
934 let parts = acc.to_array();
935 let mut m = parts[0];
936 for &p in &parts[1..] {
937 if p < m {
938 m = p;
939 }
940 }
941 for i in (chunks * 4)..len {
942 let v = unsafe { *data.add(i) };
943 if v < m {
944 m = v;
945 }
946 }
947 m
948}
949
950#[inline]
955unsafe fn simd_max_f64(data: *const f64, len: usize, threshold: usize) -> f64 {
956 use wide::f64x4;
957 debug_assert!(len > 0);
958 if unsafe { contains_nan_f64(data, len) } {
959 return f64::NAN;
960 }
961 if len < threshold {
962 let mut m = unsafe { *data };
963 for i in 1..len {
964 let v = unsafe { *data.add(i) };
965 if v > m {
966 m = v;
967 }
968 }
969 return m;
970 }
971 let chunks = len / 4;
972 let mut acc = unsafe {
973 f64x4::from([
974 *data,
975 *data.add(1),
976 *data.add(2),
977 *data.add(3),
978 ])
979 };
980 for i in 1..chunks {
981 let base = i * 4;
982 let v = unsafe {
983 f64x4::from([
984 *data.add(base),
985 *data.add(base + 1),
986 *data.add(base + 2),
987 *data.add(base + 3),
988 ])
989 };
990 acc = acc.fast_max(v);
991 }
992 let parts = acc.to_array();
993 let mut m = parts[0];
994 for &p in &parts[1..] {
995 if p > m {
996 m = p;
997 }
998 }
999 for i in (chunks * 4)..len {
1000 let v = unsafe { *data.add(i) };
1001 if v > m {
1002 m = v;
1003 }
1004 }
1005 m
1006}
1007
1008#[inline]
1016unsafe fn simd_sum_i64(data: *const i64, len: usize, threshold: usize) -> i64 {
1017 use wide::i64x4;
1018
1019 if len < threshold {
1020 let mut s: i64 = 0;
1021 for i in 0..len {
1022 s = s.wrapping_add(unsafe { *data.add(i) });
1023 }
1024 return s;
1025 }
1026
1027 let chunks = len / 4;
1028 let mut acc = i64x4::splat(0);
1029 for i in 0..chunks {
1030 let base = i * 4;
1031 let v = unsafe {
1032 i64x4::from([
1033 *data.add(base),
1034 *data.add(base + 1),
1035 *data.add(base + 2),
1036 *data.add(base + 3),
1037 ])
1038 };
1039 acc = acc + v;
1042 }
1043 let parts = acc.to_array();
1044 let mut s = parts[0]
1045 .wrapping_add(parts[1])
1046 .wrapping_add(parts[2])
1047 .wrapping_add(parts[3]);
1048 for i in (chunks * 4)..len {
1049 s = s.wrapping_add(unsafe { *data.add(i) });
1050 }
1051 s
1052}
1053
1054pub fn avg_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1058 if view.len == 0 {
1059 return match view.elem_type {
1060 V2ElemType::F64 | V2ElemType::I64 | V2ElemType::I32 => {
1061 Some((f64::NAN.to_bits(), NativeKind::Float64))
1062 }
1063 V2ElemType::Bool
1066 | V2ElemType::I8
1067 | V2ElemType::U8
1068 | V2ElemType::I16
1069 | V2ElemType::U16
1070 | V2ElemType::U32
1071 | V2ElemType::F32
1072 | V2ElemType::Char
1073 | V2ElemType::String
1074 | V2ElemType::Decimal
1075 | V2ElemType::TypedObject => None,
1076 };
1077 }
1078 match view.elem_type {
1079 V2ElemType::F64 => {
1080 let data = unsafe {
1083 let arr = view.ptr as *const TypedArray<f64>;
1084 (*arr).data as *const f64
1085 };
1086 let s = unsafe { simd_sum_f64(data, view.len as usize, 16) };
1087 Some(((s / view.len as f64).to_bits(), NativeKind::Float64))
1088 }
1089 V2ElemType::I64 => {
1090 let mut s = 0.0_f64;
1091 for i in 0..view.len {
1092 s += unsafe {
1093 let arr = view.ptr as *const TypedArray<i64>;
1094 TypedArray::<i64>::get_unchecked(arr, i) as f64
1095 };
1096 }
1097 Some(((s / view.len as f64).to_bits(), NativeKind::Float64))
1098 }
1099 V2ElemType::I32 => {
1100 let mut s = 0.0_f64;
1101 for i in 0..view.len {
1102 s += unsafe {
1103 let arr = view.ptr as *const TypedArray<i32>;
1104 TypedArray::<i32>::get_unchecked(arr, i) as f64
1105 };
1106 }
1107 Some(((s / view.len as f64).to_bits(), NativeKind::Float64))
1108 }
1109 V2ElemType::Bool
1115 | V2ElemType::I8
1116 | V2ElemType::U8
1117 | V2ElemType::I16
1118 | V2ElemType::U16
1119 | V2ElemType::U32
1120 | V2ElemType::F32
1121 | V2ElemType::Char
1122 | V2ElemType::String
1123 | V2ElemType::Decimal
1124 | V2ElemType::TypedObject => None,
1125 }
1126}
1127
1128pub fn min_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1135 if view.len == 0 {
1136 return match view.elem_type {
1137 V2ElemType::F64 => Some((f64::NAN.to_bits(), NativeKind::Float64)),
1138 V2ElemType::I64 | V2ElemType::I32 => Some((0u64, NativeKind::Bool)),
1139 V2ElemType::Bool
1143 | V2ElemType::I8
1144 | V2ElemType::U8
1145 | V2ElemType::I16
1146 | V2ElemType::U16
1147 | V2ElemType::U32
1148 | V2ElemType::F32
1149 | V2ElemType::Char
1150 | V2ElemType::String
1151 | V2ElemType::Decimal
1152 | V2ElemType::TypedObject => None,
1153 };
1154 }
1155 match view.elem_type {
1156 V2ElemType::F64 => {
1157 let data = unsafe {
1158 let arr = view.ptr as *const TypedArray<f64>;
1159 (*arr).data as *const f64
1160 };
1161 let min = unsafe { simd_min_f64(data, view.len as usize, 16) };
1162 Some((min.to_bits(), NativeKind::Float64))
1163 }
1164 V2ElemType::I64 => {
1165 let mut min = i64::MAX;
1166 for i in 0..view.len {
1167 let v = unsafe {
1168 let arr = view.ptr as *const TypedArray<i64>;
1169 TypedArray::<i64>::get_unchecked(arr, i)
1170 };
1171 if v < min {
1172 min = v;
1173 }
1174 }
1175 Some((min as u64, NativeKind::Int64))
1176 }
1177 V2ElemType::I32 => {
1178 let mut min = i32::MAX as i64;
1179 for i in 0..view.len {
1180 let v = unsafe {
1181 let arr = view.ptr as *const TypedArray<i32>;
1182 TypedArray::<i32>::get_unchecked(arr, i) as i64
1183 };
1184 if v < min {
1185 min = v;
1186 }
1187 }
1188 Some((min as u64, NativeKind::Int64))
1189 }
1190 V2ElemType::Bool
1196 | V2ElemType::I8
1197 | V2ElemType::U8
1198 | V2ElemType::I16
1199 | V2ElemType::U16
1200 | V2ElemType::U32
1201 | V2ElemType::F32
1202 | V2ElemType::Char
1203 | V2ElemType::String
1204 | V2ElemType::Decimal
1205 | V2ElemType::TypedObject => None,
1206 }
1207}
1208
1209pub fn max_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1211 if view.len == 0 {
1212 return match view.elem_type {
1213 V2ElemType::F64 => Some((f64::NAN.to_bits(), NativeKind::Float64)),
1214 V2ElemType::I64 | V2ElemType::I32 => Some((0u64, NativeKind::Bool)),
1215 V2ElemType::Bool
1219 | V2ElemType::I8
1220 | V2ElemType::U8
1221 | V2ElemType::I16
1222 | V2ElemType::U16
1223 | V2ElemType::U32
1224 | V2ElemType::F32
1225 | V2ElemType::Char
1226 | V2ElemType::String
1227 | V2ElemType::Decimal
1228 | V2ElemType::TypedObject => None,
1229 };
1230 }
1231 match view.elem_type {
1232 V2ElemType::F64 => {
1233 let data = unsafe {
1234 let arr = view.ptr as *const TypedArray<f64>;
1235 (*arr).data as *const f64
1236 };
1237 let max = unsafe { simd_max_f64(data, view.len as usize, 16) };
1238 Some((max.to_bits(), NativeKind::Float64))
1239 }
1240 V2ElemType::I64 => {
1241 let mut max = i64::MIN;
1242 for i in 0..view.len {
1243 let v = unsafe {
1244 let arr = view.ptr as *const TypedArray<i64>;
1245 TypedArray::<i64>::get_unchecked(arr, i)
1246 };
1247 if v > max {
1248 max = v;
1249 }
1250 }
1251 Some((max as u64, NativeKind::Int64))
1252 }
1253 V2ElemType::I32 => {
1254 let mut max = i32::MIN as i64;
1255 for i in 0..view.len {
1256 let v = unsafe {
1257 let arr = view.ptr as *const TypedArray<i32>;
1258 TypedArray::<i32>::get_unchecked(arr, i) as i64
1259 };
1260 if v > max {
1261 max = v;
1262 }
1263 }
1264 Some((max as u64, NativeKind::Int64))
1265 }
1266 V2ElemType::Bool
1272 | V2ElemType::I8
1273 | V2ElemType::U8
1274 | V2ElemType::I16
1275 | V2ElemType::U16
1276 | V2ElemType::U32
1277 | V2ElemType::F32
1278 | V2ElemType::Char
1279 | V2ElemType::String
1280 | V2ElemType::Decimal
1281 | V2ElemType::TypedObject => None,
1282 }
1283}
1284
1285pub fn variance_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1288 match view.elem_type {
1289 V2ElemType::F64 => {
1290 if view.len < 2 {
1291 return Some((f64::NAN.to_bits(), NativeKind::Float64));
1292 }
1293 let n = view.len as f64;
1294 let mut sum = 0.0_f64;
1295 for i in 0..view.len {
1296 sum += unsafe {
1297 let arr = view.ptr as *const TypedArray<f64>;
1298 TypedArray::<f64>::get_unchecked(arr, i)
1299 };
1300 }
1301 let mean = sum / n;
1302 let mut var_sum = 0.0_f64;
1303 for i in 0..view.len {
1304 let v = unsafe {
1305 let arr = view.ptr as *const TypedArray<f64>;
1306 TypedArray::<f64>::get_unchecked(arr, i)
1307 };
1308 let d = v - mean;
1309 var_sum += d * d;
1310 }
1311 Some(((var_sum / (n - 1.0)).to_bits(), NativeKind::Float64))
1312 }
1313 _ => None,
1314 }
1315}
1316
1317pub fn std_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1319 variance_elements(view).map(|(bits, _kind)| {
1320 let v = f64::from_bits(bits);
1321 (v.sqrt().to_bits(), NativeKind::Float64)
1322 })
1323}
1324
1325pub fn dot_elements(
1327 view_a: &V2TypedArrayView,
1328 view_b: &V2TypedArrayView,
1329) -> Option<(u64, NativeKind)> {
1330 if view_a.elem_type != V2ElemType::F64 || view_b.elem_type != V2ElemType::F64 {
1331 return None;
1332 }
1333 if view_a.len != view_b.len {
1334 return None; }
1336 let mut sum = 0.0_f64;
1337 for i in 0..view_a.len {
1338 let a = unsafe {
1339 let arr = view_a.ptr as *const TypedArray<f64>;
1340 TypedArray::<f64>::get_unchecked(arr, i)
1341 };
1342 let b = unsafe {
1343 let arr = view_b.ptr as *const TypedArray<f64>;
1344 TypedArray::<f64>::get_unchecked(arr, i)
1345 };
1346 sum += a * b;
1347 }
1348 Some((sum.to_bits(), NativeKind::Float64))
1349}
1350
1351pub fn norm_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1353 match view.elem_type {
1354 V2ElemType::F64 => {
1355 let mut sum_sq = 0.0_f64;
1356 for i in 0..view.len {
1357 let v = unsafe {
1358 let arr = view.ptr as *const TypedArray<f64>;
1359 TypedArray::<f64>::get_unchecked(arr, i)
1360 };
1361 sum_sq += v * v;
1362 }
1363 Some((sum_sq.sqrt().to_bits(), NativeKind::Float64))
1364 }
1365 _ => None,
1366 }
1367}
1368
1369pub fn count_true_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1371 match view.elem_type {
1372 V2ElemType::Bool => {
1373 let mut count = 0_i64;
1374 for i in 0..view.len {
1375 let v = unsafe {
1376 let arr = view.ptr as *const TypedArray<u8>;
1377 TypedArray::<u8>::get_unchecked(arr, i)
1378 };
1379 if v != 0 {
1380 count += 1;
1381 }
1382 }
1383 Some((count as u64, NativeKind::Int64))
1384 }
1385 _ => None,
1386 }
1387}
1388
1389pub fn any_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1391 match view.elem_type {
1392 V2ElemType::Bool => {
1393 for i in 0..view.len {
1394 let v = unsafe {
1395 let arr = view.ptr as *const TypedArray<u8>;
1396 TypedArray::<u8>::get_unchecked(arr, i)
1397 };
1398 if v != 0 {
1399 return Some((1u64, NativeKind::Bool));
1400 }
1401 }
1402 Some((0u64, NativeKind::Bool))
1403 }
1404 _ => None,
1405 }
1406}
1407
1408pub fn all_elements(view: &V2TypedArrayView) -> Option<(u64, NativeKind)> {
1410 match view.elem_type {
1411 V2ElemType::Bool => {
1412 for i in 0..view.len {
1413 let v = unsafe {
1414 let arr = view.ptr as *const TypedArray<u8>;
1415 TypedArray::<u8>::get_unchecked(arr, i)
1416 };
1417 if v == 0 {
1418 return Some((0u64, NativeKind::Bool));
1419 }
1420 }
1421 Some((1u64, NativeKind::Bool))
1422 }
1423 _ => None,
1424 }
1425}
1426
1427pub fn clone_array(view: &V2TypedArrayView) -> *mut u8 {
1430 match view.elem_type {
1431 V2ElemType::F64 => {
1432 let new_arr = TypedArray::<f64>::with_capacity(view.len);
1433 unsafe {
1434 let src = view.ptr as *const TypedArray<f64>;
1435 let src_data = (*src).data;
1436 let dst_data = (*new_arr).data;
1437 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1438 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1439 }
1440 (*new_arr).len = view.len;
1441 let p = new_arr as *mut u8;
1442 stamp_elem_type(p, ELEM_TYPE_F64);
1443 p
1444 }
1445 }
1446 V2ElemType::I64 => {
1447 let new_arr = TypedArray::<i64>::with_capacity(view.len);
1448 unsafe {
1449 let src = view.ptr as *const TypedArray<i64>;
1450 let src_data = (*src).data;
1451 let dst_data = (*new_arr).data;
1452 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1453 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1454 }
1455 (*new_arr).len = view.len;
1456 let p = new_arr as *mut u8;
1457 stamp_elem_type(p, ELEM_TYPE_I64);
1458 p
1459 }
1460 }
1461 V2ElemType::I32 => {
1462 let new_arr = TypedArray::<i32>::with_capacity(view.len);
1463 unsafe {
1464 let src = view.ptr as *const TypedArray<i32>;
1465 let src_data = (*src).data;
1466 let dst_data = (*new_arr).data;
1467 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1468 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1469 }
1470 (*new_arr).len = view.len;
1471 let p = new_arr as *mut u8;
1472 stamp_elem_type(p, ELEM_TYPE_I32);
1473 p
1474 }
1475 }
1476 V2ElemType::Bool => {
1477 let new_arr = TypedArray::<u8>::with_capacity(view.len);
1478 unsafe {
1479 let src = view.ptr as *const TypedArray<u8>;
1480 let src_data = (*src).data;
1481 let dst_data = (*new_arr).data;
1482 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1483 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1484 }
1485 (*new_arr).len = view.len;
1486 let p = new_arr as *mut u8;
1487 stamp_elem_type(p, ELEM_TYPE_BOOL);
1488 p
1489 }
1490 }
1491 V2ElemType::I8 => {
1496 let new_arr = TypedArray::<i8>::with_capacity(view.len);
1497 unsafe {
1498 let src = view.ptr as *const TypedArray<i8>;
1499 let src_data = (*src).data;
1500 let dst_data = (*new_arr).data;
1501 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1502 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1503 }
1504 (*new_arr).len = view.len;
1505 let p = new_arr as *mut u8;
1506 stamp_elem_type(p, ELEM_TYPE_I8);
1507 p
1508 }
1509 }
1510 V2ElemType::U8 => {
1511 let new_arr = TypedArray::<u8>::with_capacity(view.len);
1512 unsafe {
1513 let src = view.ptr as *const TypedArray<u8>;
1514 let src_data = (*src).data;
1515 let dst_data = (*new_arr).data;
1516 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1517 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1518 }
1519 (*new_arr).len = view.len;
1520 let p = new_arr as *mut u8;
1521 stamp_elem_type(p, ELEM_TYPE_U8);
1522 p
1523 }
1524 }
1525 V2ElemType::I16 => {
1526 let new_arr = TypedArray::<i16>::with_capacity(view.len);
1527 unsafe {
1528 let src = view.ptr as *const TypedArray<i16>;
1529 let src_data = (*src).data;
1530 let dst_data = (*new_arr).data;
1531 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1532 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1533 }
1534 (*new_arr).len = view.len;
1535 let p = new_arr as *mut u8;
1536 stamp_elem_type(p, ELEM_TYPE_I16);
1537 p
1538 }
1539 }
1540 V2ElemType::U16 => {
1541 let new_arr = TypedArray::<u16>::with_capacity(view.len);
1542 unsafe {
1543 let src = view.ptr as *const TypedArray<u16>;
1544 let src_data = (*src).data;
1545 let dst_data = (*new_arr).data;
1546 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1547 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1548 }
1549 (*new_arr).len = view.len;
1550 let p = new_arr as *mut u8;
1551 stamp_elem_type(p, ELEM_TYPE_U16);
1552 p
1553 }
1554 }
1555 V2ElemType::U32 => {
1556 let new_arr = TypedArray::<u32>::with_capacity(view.len);
1557 unsafe {
1558 let src = view.ptr as *const TypedArray<u32>;
1559 let src_data = (*src).data;
1560 let dst_data = (*new_arr).data;
1561 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1562 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1563 }
1564 (*new_arr).len = view.len;
1565 let p = new_arr as *mut u8;
1566 stamp_elem_type(p, ELEM_TYPE_U32);
1567 p
1568 }
1569 }
1570 V2ElemType::F32 => {
1573 let new_arr = TypedArray::<f32>::with_capacity(view.len);
1574 unsafe {
1575 let src = view.ptr as *const TypedArray<f32>;
1576 let src_data = (*src).data;
1577 let dst_data = (*new_arr).data;
1578 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1579 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1580 }
1581 (*new_arr).len = view.len;
1582 let p = new_arr as *mut u8;
1583 stamp_elem_type(p, ELEM_TYPE_F32);
1584 p
1585 }
1586 }
1587 V2ElemType::Char => {
1588 let new_arr = TypedArray::<char>::with_capacity(view.len);
1589 unsafe {
1590 let src = view.ptr as *const TypedArray<char>;
1591 let src_data = (*src).data;
1592 let dst_data = (*new_arr).data;
1593 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1594 std::ptr::copy_nonoverlapping(src_data, dst_data, view.len as usize);
1595 }
1596 (*new_arr).len = view.len;
1597 let p = new_arr as *mut u8;
1598 stamp_elem_type(p, ELEM_TYPE_CHAR);
1599 p
1600 }
1601 }
1602 V2ElemType::String => {
1607 let new_arr = TypedArray::<*const StringObj>::with_capacity(view.len);
1608 unsafe {
1609 let src = view.ptr as *const TypedArray<*const StringObj>;
1610 let src_data = (*src).data;
1611 let dst_data = (*new_arr).data;
1612 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1613 for i in 0..(view.len as usize) {
1614 let elem = *src_data.add(i);
1615 v2_retain(&(*elem).header);
1616 *dst_data.add(i) = elem;
1617 }
1618 }
1619 (*new_arr).len = view.len;
1620 let p = new_arr as *mut u8;
1621 stamp_elem_type(p, ELEM_TYPE_STRING);
1622 p
1623 }
1624 }
1625 V2ElemType::Decimal => {
1626 let new_arr = TypedArray::<*const DecimalObj>::with_capacity(view.len);
1627 unsafe {
1628 let src = view.ptr as *const TypedArray<*const DecimalObj>;
1629 let src_data = (*src).data;
1630 let dst_data = (*new_arr).data;
1631 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1632 for i in 0..(view.len as usize) {
1633 let elem = *src_data.add(i);
1634 v2_retain(&(*elem).header);
1635 *dst_data.add(i) = elem;
1636 }
1637 }
1638 (*new_arr).len = view.len;
1639 let p = new_arr as *mut u8;
1640 stamp_elem_type(p, ELEM_TYPE_DECIMAL);
1641 p
1642 }
1643 }
1644 V2ElemType::TypedObject => {
1650 let new_arr =
1651 TypedArray::<*const TypedObjectStorage>::with_capacity(view.len);
1652 unsafe {
1653 let src = view.ptr as *const TypedArray<*const TypedObjectStorage>;
1654 let src_data = (*src).data;
1655 let dst_data = (*new_arr).data;
1656 if view.len > 0 && !src_data.is_null() && !dst_data.is_null() {
1657 for i in 0..(view.len as usize) {
1658 let elem = *src_data.add(i);
1659 v2_retain(&(*elem).header);
1660 *dst_data.add(i) = elem;
1661 }
1662 }
1663 (*new_arr).len = view.len;
1664 let p = new_arr as *mut u8;
1665 stamp_elem_type(p, ELEM_TYPE_TYPED_OBJECT);
1666 p
1667 }
1668 }
1669 }
1670}
1671
1672const SIMD_UNARY_THRESHOLD: u32 = 16;
1692
1693pub fn unary_f64_transform(
1702 view: &V2TypedArrayView,
1703 simd_op: fn(wide::f64x4) -> wide::f64x4,
1704 scalar_op: fn(f64) -> f64,
1705) -> Option<*mut u8> {
1706 use wide::f64x4;
1707
1708 if view.elem_type != V2ElemType::F64 {
1709 return None;
1710 }
1711 let len = view.len;
1712 let out = TypedArray::<f64>::with_capacity(len);
1713 if len == 0 {
1714 unsafe {
1715 (*out).len = 0;
1716 let p = out as *mut u8;
1717 stamp_elem_type(p, ELEM_TYPE_F64);
1718 return Some(p);
1719 }
1720 }
1721
1722 unsafe {
1723 let src_arr = view.ptr as *const TypedArray<f64>;
1724 let src = (*src_arr).data as *const f64;
1725 let dst = (*out).data as *mut f64;
1726
1727 if len >= SIMD_UNARY_THRESHOLD {
1728 let chunks = (len / 4) as usize;
1729 for i in 0..chunks {
1730 let base = i * 4;
1731 let v = f64x4::from([
1732 *src.add(base),
1733 *src.add(base + 1),
1734 *src.add(base + 2),
1735 *src.add(base + 3),
1736 ]);
1737 let r = simd_op(v);
1738 let arr = r.to_array();
1739 *dst.add(base) = arr[0];
1740 *dst.add(base + 1) = arr[1];
1741 *dst.add(base + 2) = arr[2];
1742 *dst.add(base + 3) = arr[3];
1743 }
1744 for i in (chunks * 4)..(len as usize) {
1745 *dst.add(i) = scalar_op(*src.add(i));
1746 }
1747 } else {
1748 for i in 0..(len as usize) {
1749 *dst.add(i) = scalar_op(*src.add(i));
1750 }
1751 }
1752
1753 (*out).len = len;
1754 let p = out as *mut u8;
1755 stamp_elem_type(p, ELEM_TYPE_F64);
1756 Some(p)
1757 }
1758}
1759
1760pub fn diff_f64(view: &V2TypedArrayView) -> Option<*mut u8> {
1767 use wide::f64x4;
1768
1769 if view.elem_type != V2ElemType::F64 {
1770 return None;
1771 }
1772 let len = view.len;
1773 if len < 2 {
1774 let out = TypedArray::<f64>::with_capacity(0);
1775 unsafe {
1776 (*out).len = 0;
1777 let p = out as *mut u8;
1778 stamp_elem_type(p, ELEM_TYPE_F64);
1779 return Some(p);
1780 }
1781 }
1782
1783 let out_len = len - 1;
1784 let out = TypedArray::<f64>::with_capacity(out_len);
1785 unsafe {
1786 let src_arr = view.ptr as *const TypedArray<f64>;
1787 let src = (*src_arr).data as *const f64;
1788 let dst = (*out).data as *mut f64;
1789
1790 if out_len >= SIMD_UNARY_THRESHOLD {
1791 let mut i: usize = 0;
1792 while i + 4 < (len as usize) {
1794 let prev = f64x4::from([
1795 *src.add(i),
1796 *src.add(i + 1),
1797 *src.add(i + 2),
1798 *src.add(i + 3),
1799 ]);
1800 let next = f64x4::from([
1801 *src.add(i + 1),
1802 *src.add(i + 2),
1803 *src.add(i + 3),
1804 *src.add(i + 4),
1805 ]);
1806 let d = next - prev;
1807 let arr = d.to_array();
1808 *dst.add(i) = arr[0];
1809 *dst.add(i + 1) = arr[1];
1810 *dst.add(i + 2) = arr[2];
1811 *dst.add(i + 3) = arr[3];
1812 i += 4;
1813 }
1814 for j in i..(out_len as usize) {
1816 *dst.add(j) = *src.add(j + 1) - *src.add(j);
1817 }
1818 } else {
1819 for i in 0..(out_len as usize) {
1820 *dst.add(i) = *src.add(i + 1) - *src.add(i);
1821 }
1822 }
1823
1824 (*out).len = out_len;
1825 let p = out as *mut u8;
1826 stamp_elem_type(p, ELEM_TYPE_F64);
1827 Some(p)
1828 }
1829}
1830
1831pub fn reverse_array(view: &V2TypedArrayView) -> *mut u8 {
1856 #[inline]
1858 unsafe fn copy_reverse_scalar<T: Copy>(
1859 src_data: *const T,
1860 dst_data: *mut T,
1861 len: usize,
1862 ) {
1863 if len == 0 || src_data.is_null() || dst_data.is_null() {
1864 return;
1865 }
1866 for i in 0..len {
1867 unsafe {
1868 *dst_data.add(i) = *src_data.add(len - 1 - i);
1869 }
1870 }
1871 }
1872
1873 match view.elem_type {
1874 V2ElemType::F64 => {
1875 let new_arr = TypedArray::<f64>::with_capacity(view.len);
1876 unsafe {
1877 let src = view.ptr as *const TypedArray<f64>;
1878 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1879 (*new_arr).len = view.len;
1880 let p = new_arr as *mut u8;
1881 stamp_elem_type(p, ELEM_TYPE_F64);
1882 p
1883 }
1884 }
1885 V2ElemType::I64 => {
1886 let new_arr = TypedArray::<i64>::with_capacity(view.len);
1887 unsafe {
1888 let src = view.ptr as *const TypedArray<i64>;
1889 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1890 (*new_arr).len = view.len;
1891 let p = new_arr as *mut u8;
1892 stamp_elem_type(p, ELEM_TYPE_I64);
1893 p
1894 }
1895 }
1896 V2ElemType::I32 => {
1897 let new_arr = TypedArray::<i32>::with_capacity(view.len);
1898 unsafe {
1899 let src = view.ptr as *const TypedArray<i32>;
1900 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1901 (*new_arr).len = view.len;
1902 let p = new_arr as *mut u8;
1903 stamp_elem_type(p, ELEM_TYPE_I32);
1904 p
1905 }
1906 }
1907 V2ElemType::Bool => {
1908 let new_arr = TypedArray::<u8>::with_capacity(view.len);
1909 unsafe {
1910 let src = view.ptr as *const TypedArray<u8>;
1911 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1912 (*new_arr).len = view.len;
1913 let p = new_arr as *mut u8;
1914 stamp_elem_type(p, ELEM_TYPE_BOOL);
1915 p
1916 }
1917 }
1918 V2ElemType::I8 => {
1919 let new_arr = TypedArray::<i8>::with_capacity(view.len);
1920 unsafe {
1921 let src = view.ptr as *const TypedArray<i8>;
1922 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1923 (*new_arr).len = view.len;
1924 let p = new_arr as *mut u8;
1925 stamp_elem_type(p, ELEM_TYPE_I8);
1926 p
1927 }
1928 }
1929 V2ElemType::U8 => {
1930 let new_arr = TypedArray::<u8>::with_capacity(view.len);
1931 unsafe {
1932 let src = view.ptr as *const TypedArray<u8>;
1933 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1934 (*new_arr).len = view.len;
1935 let p = new_arr as *mut u8;
1936 stamp_elem_type(p, ELEM_TYPE_U8);
1937 p
1938 }
1939 }
1940 V2ElemType::I16 => {
1941 let new_arr = TypedArray::<i16>::with_capacity(view.len);
1942 unsafe {
1943 let src = view.ptr as *const TypedArray<i16>;
1944 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1945 (*new_arr).len = view.len;
1946 let p = new_arr as *mut u8;
1947 stamp_elem_type(p, ELEM_TYPE_I16);
1948 p
1949 }
1950 }
1951 V2ElemType::U16 => {
1952 let new_arr = TypedArray::<u16>::with_capacity(view.len);
1953 unsafe {
1954 let src = view.ptr as *const TypedArray<u16>;
1955 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1956 (*new_arr).len = view.len;
1957 let p = new_arr as *mut u8;
1958 stamp_elem_type(p, ELEM_TYPE_U16);
1959 p
1960 }
1961 }
1962 V2ElemType::U32 => {
1963 let new_arr = TypedArray::<u32>::with_capacity(view.len);
1964 unsafe {
1965 let src = view.ptr as *const TypedArray<u32>;
1966 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1967 (*new_arr).len = view.len;
1968 let p = new_arr as *mut u8;
1969 stamp_elem_type(p, ELEM_TYPE_U32);
1970 p
1971 }
1972 }
1973 V2ElemType::F32 => {
1974 let new_arr = TypedArray::<f32>::with_capacity(view.len);
1975 unsafe {
1976 let src = view.ptr as *const TypedArray<f32>;
1977 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1978 (*new_arr).len = view.len;
1979 let p = new_arr as *mut u8;
1980 stamp_elem_type(p, ELEM_TYPE_F32);
1981 p
1982 }
1983 }
1984 V2ElemType::Char => {
1985 let new_arr = TypedArray::<char>::with_capacity(view.len);
1986 unsafe {
1987 let src = view.ptr as *const TypedArray<char>;
1988 copy_reverse_scalar((*src).data, (*new_arr).data, view.len as usize);
1989 (*new_arr).len = view.len;
1990 let p = new_arr as *mut u8;
1991 stamp_elem_type(p, ELEM_TYPE_CHAR);
1992 p
1993 }
1994 }
1995 V2ElemType::String => {
1996 let new_arr = TypedArray::<*const StringObj>::with_capacity(view.len);
1997 unsafe {
1998 let src = view.ptr as *const TypedArray<*const StringObj>;
1999 let src_data = (*src).data;
2000 let dst_data = (*new_arr).data;
2001 let len = view.len as usize;
2002 if len > 0 && !src_data.is_null() && !dst_data.is_null() {
2003 for i in 0..len {
2004 let elem = *src_data.add(len - 1 - i);
2005 v2_retain(&(*elem).header);
2006 *dst_data.add(i) = elem;
2007 }
2008 }
2009 (*new_arr).len = view.len;
2010 let p = new_arr as *mut u8;
2011 stamp_elem_type(p, ELEM_TYPE_STRING);
2012 p
2013 }
2014 }
2015 V2ElemType::Decimal => {
2016 let new_arr = TypedArray::<*const DecimalObj>::with_capacity(view.len);
2017 unsafe {
2018 let src = view.ptr as *const TypedArray<*const DecimalObj>;
2019 let src_data = (*src).data;
2020 let dst_data = (*new_arr).data;
2021 let len = view.len as usize;
2022 if len > 0 && !src_data.is_null() && !dst_data.is_null() {
2023 for i in 0..len {
2024 let elem = *src_data.add(len - 1 - i);
2025 v2_retain(&(*elem).header);
2026 *dst_data.add(i) = elem;
2027 }
2028 }
2029 (*new_arr).len = view.len;
2030 let p = new_arr as *mut u8;
2031 stamp_elem_type(p, ELEM_TYPE_DECIMAL);
2032 p
2033 }
2034 }
2035 V2ElemType::TypedObject => {
2036 let new_arr =
2037 TypedArray::<*const TypedObjectStorage>::with_capacity(view.len);
2038 unsafe {
2039 let src = view.ptr as *const TypedArray<*const TypedObjectStorage>;
2040 let src_data = (*src).data;
2041 let dst_data = (*new_arr).data;
2042 let len = view.len as usize;
2043 if len > 0 && !src_data.is_null() && !dst_data.is_null() {
2044 for i in 0..len {
2045 let elem = *src_data.add(len - 1 - i);
2046 v2_retain(&(*elem).header);
2047 *dst_data.add(i) = elem;
2048 }
2049 }
2050 (*new_arr).len = view.len;
2051 let p = new_arr as *mut u8;
2052 stamp_elem_type(p, ELEM_TYPE_TYPED_OBJECT);
2053 p
2054 }
2055 }
2056 }
2057}
2058
2059pub fn concat_arrays(
2068 a: &V2TypedArrayView,
2069 b: &V2TypedArrayView,
2070) -> Result<*mut u8, &'static str> {
2071 if a.elem_type != b.elem_type {
2072 return Err("concat_arrays: element type mismatch");
2073 }
2074 let total_len = a
2075 .len
2076 .checked_add(b.len)
2077 .ok_or("concat_arrays: result length overflow")?;
2078
2079 #[inline]
2081 unsafe fn copy_two_scalar<T: Copy>(
2082 a_data: *const T,
2083 a_len: usize,
2084 b_data: *const T,
2085 b_len: usize,
2086 dst_data: *mut T,
2087 ) {
2088 if dst_data.is_null() {
2089 return;
2090 }
2091 if a_len > 0 && !a_data.is_null() {
2092 unsafe { std::ptr::copy_nonoverlapping(a_data, dst_data, a_len) };
2093 }
2094 if b_len > 0 && !b_data.is_null() {
2095 unsafe { std::ptr::copy_nonoverlapping(b_data, dst_data.add(a_len), b_len) };
2096 }
2097 }
2098
2099 let result = match a.elem_type {
2100 V2ElemType::F64 => unsafe {
2101 let new_arr = TypedArray::<f64>::with_capacity(total_len);
2102 let a_arr = a.ptr as *const TypedArray<f64>;
2103 let b_arr = b.ptr as *const TypedArray<f64>;
2104 copy_two_scalar(
2105 (*a_arr).data,
2106 a.len as usize,
2107 (*b_arr).data,
2108 b.len as usize,
2109 (*new_arr).data,
2110 );
2111 (*new_arr).len = total_len;
2112 let p = new_arr as *mut u8;
2113 stamp_elem_type(p, ELEM_TYPE_F64);
2114 p
2115 },
2116 V2ElemType::I64 => unsafe {
2117 let new_arr = TypedArray::<i64>::with_capacity(total_len);
2118 let a_arr = a.ptr as *const TypedArray<i64>;
2119 let b_arr = b.ptr as *const TypedArray<i64>;
2120 copy_two_scalar(
2121 (*a_arr).data,
2122 a.len as usize,
2123 (*b_arr).data,
2124 b.len as usize,
2125 (*new_arr).data,
2126 );
2127 (*new_arr).len = total_len;
2128 let p = new_arr as *mut u8;
2129 stamp_elem_type(p, ELEM_TYPE_I64);
2130 p
2131 },
2132 V2ElemType::I32 => unsafe {
2133 let new_arr = TypedArray::<i32>::with_capacity(total_len);
2134 let a_arr = a.ptr as *const TypedArray<i32>;
2135 let b_arr = b.ptr as *const TypedArray<i32>;
2136 copy_two_scalar(
2137 (*a_arr).data,
2138 a.len as usize,
2139 (*b_arr).data,
2140 b.len as usize,
2141 (*new_arr).data,
2142 );
2143 (*new_arr).len = total_len;
2144 let p = new_arr as *mut u8;
2145 stamp_elem_type(p, ELEM_TYPE_I32);
2146 p
2147 },
2148 V2ElemType::Bool => unsafe {
2149 let new_arr = TypedArray::<u8>::with_capacity(total_len);
2150 let a_arr = a.ptr as *const TypedArray<u8>;
2151 let b_arr = b.ptr as *const TypedArray<u8>;
2152 copy_two_scalar(
2153 (*a_arr).data,
2154 a.len as usize,
2155 (*b_arr).data,
2156 b.len as usize,
2157 (*new_arr).data,
2158 );
2159 (*new_arr).len = total_len;
2160 let p = new_arr as *mut u8;
2161 stamp_elem_type(p, ELEM_TYPE_BOOL);
2162 p
2163 },
2164 V2ElemType::I8 => unsafe {
2165 let new_arr = TypedArray::<i8>::with_capacity(total_len);
2166 let a_arr = a.ptr as *const TypedArray<i8>;
2167 let b_arr = b.ptr as *const TypedArray<i8>;
2168 copy_two_scalar(
2169 (*a_arr).data,
2170 a.len as usize,
2171 (*b_arr).data,
2172 b.len as usize,
2173 (*new_arr).data,
2174 );
2175 (*new_arr).len = total_len;
2176 let p = new_arr as *mut u8;
2177 stamp_elem_type(p, ELEM_TYPE_I8);
2178 p
2179 },
2180 V2ElemType::U8 => unsafe {
2181 let new_arr = TypedArray::<u8>::with_capacity(total_len);
2182 let a_arr = a.ptr as *const TypedArray<u8>;
2183 let b_arr = b.ptr as *const TypedArray<u8>;
2184 copy_two_scalar(
2185 (*a_arr).data,
2186 a.len as usize,
2187 (*b_arr).data,
2188 b.len as usize,
2189 (*new_arr).data,
2190 );
2191 (*new_arr).len = total_len;
2192 let p = new_arr as *mut u8;
2193 stamp_elem_type(p, ELEM_TYPE_U8);
2194 p
2195 },
2196 V2ElemType::I16 => unsafe {
2197 let new_arr = TypedArray::<i16>::with_capacity(total_len);
2198 let a_arr = a.ptr as *const TypedArray<i16>;
2199 let b_arr = b.ptr as *const TypedArray<i16>;
2200 copy_two_scalar(
2201 (*a_arr).data,
2202 a.len as usize,
2203 (*b_arr).data,
2204 b.len as usize,
2205 (*new_arr).data,
2206 );
2207 (*new_arr).len = total_len;
2208 let p = new_arr as *mut u8;
2209 stamp_elem_type(p, ELEM_TYPE_I16);
2210 p
2211 },
2212 V2ElemType::U16 => unsafe {
2213 let new_arr = TypedArray::<u16>::with_capacity(total_len);
2214 let a_arr = a.ptr as *const TypedArray<u16>;
2215 let b_arr = b.ptr as *const TypedArray<u16>;
2216 copy_two_scalar(
2217 (*a_arr).data,
2218 a.len as usize,
2219 (*b_arr).data,
2220 b.len as usize,
2221 (*new_arr).data,
2222 );
2223 (*new_arr).len = total_len;
2224 let p = new_arr as *mut u8;
2225 stamp_elem_type(p, ELEM_TYPE_U16);
2226 p
2227 },
2228 V2ElemType::U32 => unsafe {
2229 let new_arr = TypedArray::<u32>::with_capacity(total_len);
2230 let a_arr = a.ptr as *const TypedArray<u32>;
2231 let b_arr = b.ptr as *const TypedArray<u32>;
2232 copy_two_scalar(
2233 (*a_arr).data,
2234 a.len as usize,
2235 (*b_arr).data,
2236 b.len as usize,
2237 (*new_arr).data,
2238 );
2239 (*new_arr).len = total_len;
2240 let p = new_arr as *mut u8;
2241 stamp_elem_type(p, ELEM_TYPE_U32);
2242 p
2243 },
2244 V2ElemType::F32 => unsafe {
2245 let new_arr = TypedArray::<f32>::with_capacity(total_len);
2246 let a_arr = a.ptr as *const TypedArray<f32>;
2247 let b_arr = b.ptr as *const TypedArray<f32>;
2248 copy_two_scalar(
2249 (*a_arr).data,
2250 a.len as usize,
2251 (*b_arr).data,
2252 b.len as usize,
2253 (*new_arr).data,
2254 );
2255 (*new_arr).len = total_len;
2256 let p = new_arr as *mut u8;
2257 stamp_elem_type(p, ELEM_TYPE_F32);
2258 p
2259 },
2260 V2ElemType::Char => unsafe {
2261 let new_arr = TypedArray::<char>::with_capacity(total_len);
2262 let a_arr = a.ptr as *const TypedArray<char>;
2263 let b_arr = b.ptr as *const TypedArray<char>;
2264 copy_two_scalar(
2265 (*a_arr).data,
2266 a.len as usize,
2267 (*b_arr).data,
2268 b.len as usize,
2269 (*new_arr).data,
2270 );
2271 (*new_arr).len = total_len;
2272 let p = new_arr as *mut u8;
2273 stamp_elem_type(p, ELEM_TYPE_CHAR);
2274 p
2275 },
2276 V2ElemType::String => unsafe {
2277 let new_arr = TypedArray::<*const StringObj>::with_capacity(total_len);
2278 let a_arr = a.ptr as *const TypedArray<*const StringObj>;
2279 let b_arr = b.ptr as *const TypedArray<*const StringObj>;
2280 let dst_data = (*new_arr).data;
2281 let a_data = (*a_arr).data;
2282 let b_data = (*b_arr).data;
2283 if !dst_data.is_null() {
2284 if a.len > 0 && !a_data.is_null() {
2285 for i in 0..(a.len as usize) {
2286 let elem = *a_data.add(i);
2287 v2_retain(&(*elem).header);
2288 *dst_data.add(i) = elem;
2289 }
2290 }
2291 if b.len > 0 && !b_data.is_null() {
2292 let off = a.len as usize;
2293 for i in 0..(b.len as usize) {
2294 let elem = *b_data.add(i);
2295 v2_retain(&(*elem).header);
2296 *dst_data.add(off + i) = elem;
2297 }
2298 }
2299 }
2300 (*new_arr).len = total_len;
2301 let p = new_arr as *mut u8;
2302 stamp_elem_type(p, ELEM_TYPE_STRING);
2303 p
2304 },
2305 V2ElemType::Decimal => unsafe {
2306 let new_arr = TypedArray::<*const DecimalObj>::with_capacity(total_len);
2307 let a_arr = a.ptr as *const TypedArray<*const DecimalObj>;
2308 let b_arr = b.ptr as *const TypedArray<*const DecimalObj>;
2309 let dst_data = (*new_arr).data;
2310 let a_data = (*a_arr).data;
2311 let b_data = (*b_arr).data;
2312 if !dst_data.is_null() {
2313 if a.len > 0 && !a_data.is_null() {
2314 for i in 0..(a.len as usize) {
2315 let elem = *a_data.add(i);
2316 v2_retain(&(*elem).header);
2317 *dst_data.add(i) = elem;
2318 }
2319 }
2320 if b.len > 0 && !b_data.is_null() {
2321 let off = a.len as usize;
2322 for i in 0..(b.len as usize) {
2323 let elem = *b_data.add(i);
2324 v2_retain(&(*elem).header);
2325 *dst_data.add(off + i) = elem;
2326 }
2327 }
2328 }
2329 (*new_arr).len = total_len;
2330 let p = new_arr as *mut u8;
2331 stamp_elem_type(p, ELEM_TYPE_DECIMAL);
2332 p
2333 },
2334 V2ElemType::TypedObject => unsafe {
2335 let new_arr =
2336 TypedArray::<*const TypedObjectStorage>::with_capacity(total_len);
2337 let a_arr = a.ptr as *const TypedArray<*const TypedObjectStorage>;
2338 let b_arr = b.ptr as *const TypedArray<*const TypedObjectStorage>;
2339 let dst_data = (*new_arr).data;
2340 let a_data = (*a_arr).data;
2341 let b_data = (*b_arr).data;
2342 if !dst_data.is_null() {
2343 if a.len > 0 && !a_data.is_null() {
2344 for i in 0..(a.len as usize) {
2345 let elem = *a_data.add(i);
2346 v2_retain(&(*elem).header);
2347 *dst_data.add(i) = elem;
2348 }
2349 }
2350 if b.len > 0 && !b_data.is_null() {
2351 let off = a.len as usize;
2352 for i in 0..(b.len as usize) {
2353 let elem = *b_data.add(i);
2354 v2_retain(&(*elem).header);
2355 *dst_data.add(off + i) = elem;
2356 }
2357 }
2358 }
2359 (*new_arr).len = total_len;
2360 let p = new_arr as *mut u8;
2361 stamp_elem_type(p, ELEM_TYPE_TYPED_OBJECT);
2362 p
2363 },
2364 };
2365 Ok(result)
2366}
2367
2368fn copy_range_to_new_array(
2375 view: &V2TypedArrayView,
2376 start: u32,
2377 end: u32,
2378) -> *mut u8 {
2379 let start = start.min(view.len);
2381 let end = end.min(view.len);
2382 let out_len = end.saturating_sub(start);
2383 let s = start as usize;
2384 let n = out_len as usize;
2385
2386 #[inline]
2389 unsafe fn copy_scalar_range<T: Copy>(
2390 src_data: *const T,
2391 dst_data: *mut T,
2392 start: usize,
2393 len: usize,
2394 ) {
2395 if len == 0 || src_data.is_null() || dst_data.is_null() {
2396 return;
2397 }
2398 unsafe {
2399 std::ptr::copy_nonoverlapping(src_data.add(start), dst_data, len);
2400 }
2401 }
2402
2403 match view.elem_type {
2404 V2ElemType::F64 => unsafe {
2405 let new_arr = TypedArray::<f64>::with_capacity(out_len);
2406 let src = view.ptr as *const TypedArray<f64>;
2407 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2408 (*new_arr).len = out_len;
2409 let p = new_arr as *mut u8;
2410 stamp_elem_type(p, ELEM_TYPE_F64);
2411 p
2412 },
2413 V2ElemType::I64 => unsafe {
2414 let new_arr = TypedArray::<i64>::with_capacity(out_len);
2415 let src = view.ptr as *const TypedArray<i64>;
2416 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2417 (*new_arr).len = out_len;
2418 let p = new_arr as *mut u8;
2419 stamp_elem_type(p, ELEM_TYPE_I64);
2420 p
2421 },
2422 V2ElemType::I32 => unsafe {
2423 let new_arr = TypedArray::<i32>::with_capacity(out_len);
2424 let src = view.ptr as *const TypedArray<i32>;
2425 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2426 (*new_arr).len = out_len;
2427 let p = new_arr as *mut u8;
2428 stamp_elem_type(p, ELEM_TYPE_I32);
2429 p
2430 },
2431 V2ElemType::Bool => unsafe {
2432 let new_arr = TypedArray::<u8>::with_capacity(out_len);
2433 let src = view.ptr as *const TypedArray<u8>;
2434 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2435 (*new_arr).len = out_len;
2436 let p = new_arr as *mut u8;
2437 stamp_elem_type(p, ELEM_TYPE_BOOL);
2438 p
2439 },
2440 V2ElemType::I8 => unsafe {
2441 let new_arr = TypedArray::<i8>::with_capacity(out_len);
2442 let src = view.ptr as *const TypedArray<i8>;
2443 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2444 (*new_arr).len = out_len;
2445 let p = new_arr as *mut u8;
2446 stamp_elem_type(p, ELEM_TYPE_I8);
2447 p
2448 },
2449 V2ElemType::U8 => unsafe {
2450 let new_arr = TypedArray::<u8>::with_capacity(out_len);
2451 let src = view.ptr as *const TypedArray<u8>;
2452 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2453 (*new_arr).len = out_len;
2454 let p = new_arr as *mut u8;
2455 stamp_elem_type(p, ELEM_TYPE_U8);
2456 p
2457 },
2458 V2ElemType::I16 => unsafe {
2459 let new_arr = TypedArray::<i16>::with_capacity(out_len);
2460 let src = view.ptr as *const TypedArray<i16>;
2461 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2462 (*new_arr).len = out_len;
2463 let p = new_arr as *mut u8;
2464 stamp_elem_type(p, ELEM_TYPE_I16);
2465 p
2466 },
2467 V2ElemType::U16 => unsafe {
2468 let new_arr = TypedArray::<u16>::with_capacity(out_len);
2469 let src = view.ptr as *const TypedArray<u16>;
2470 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2471 (*new_arr).len = out_len;
2472 let p = new_arr as *mut u8;
2473 stamp_elem_type(p, ELEM_TYPE_U16);
2474 p
2475 },
2476 V2ElemType::U32 => unsafe {
2477 let new_arr = TypedArray::<u32>::with_capacity(out_len);
2478 let src = view.ptr as *const TypedArray<u32>;
2479 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2480 (*new_arr).len = out_len;
2481 let p = new_arr as *mut u8;
2482 stamp_elem_type(p, ELEM_TYPE_U32);
2483 p
2484 },
2485 V2ElemType::F32 => unsafe {
2486 let new_arr = TypedArray::<f32>::with_capacity(out_len);
2487 let src = view.ptr as *const TypedArray<f32>;
2488 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2489 (*new_arr).len = out_len;
2490 let p = new_arr as *mut u8;
2491 stamp_elem_type(p, ELEM_TYPE_F32);
2492 p
2493 },
2494 V2ElemType::Char => unsafe {
2495 let new_arr = TypedArray::<char>::with_capacity(out_len);
2496 let src = view.ptr as *const TypedArray<char>;
2497 copy_scalar_range((*src).data, (*new_arr).data, s, n);
2498 (*new_arr).len = out_len;
2499 let p = new_arr as *mut u8;
2500 stamp_elem_type(p, ELEM_TYPE_CHAR);
2501 p
2502 },
2503 V2ElemType::String => unsafe {
2504 let new_arr = TypedArray::<*const StringObj>::with_capacity(out_len);
2505 let src = view.ptr as *const TypedArray<*const StringObj>;
2506 let src_data = (*src).data;
2507 let dst_data = (*new_arr).data;
2508 if n > 0 && !src_data.is_null() && !dst_data.is_null() {
2509 for i in 0..n {
2510 let elem = *src_data.add(s + i);
2511 v2_retain(&(*elem).header);
2512 *dst_data.add(i) = elem;
2513 }
2514 }
2515 (*new_arr).len = out_len;
2516 let p = new_arr as *mut u8;
2517 stamp_elem_type(p, ELEM_TYPE_STRING);
2518 p
2519 },
2520 V2ElemType::Decimal => unsafe {
2521 let new_arr = TypedArray::<*const DecimalObj>::with_capacity(out_len);
2522 let src = view.ptr as *const TypedArray<*const DecimalObj>;
2523 let src_data = (*src).data;
2524 let dst_data = (*new_arr).data;
2525 if n > 0 && !src_data.is_null() && !dst_data.is_null() {
2526 for i in 0..n {
2527 let elem = *src_data.add(s + i);
2528 v2_retain(&(*elem).header);
2529 *dst_data.add(i) = elem;
2530 }
2531 }
2532 (*new_arr).len = out_len;
2533 let p = new_arr as *mut u8;
2534 stamp_elem_type(p, ELEM_TYPE_DECIMAL);
2535 p
2536 },
2537 V2ElemType::TypedObject => unsafe {
2538 let new_arr =
2539 TypedArray::<*const TypedObjectStorage>::with_capacity(out_len);
2540 let src = view.ptr as *const TypedArray<*const TypedObjectStorage>;
2541 let src_data = (*src).data;
2542 let dst_data = (*new_arr).data;
2543 if n > 0 && !src_data.is_null() && !dst_data.is_null() {
2544 for i in 0..n {
2545 let elem = *src_data.add(s + i);
2546 v2_retain(&(*elem).header);
2547 *dst_data.add(i) = elem;
2548 }
2549 }
2550 (*new_arr).len = out_len;
2551 let p = new_arr as *mut u8;
2552 stamp_elem_type(p, ELEM_TYPE_TYPED_OBJECT);
2553 p
2554 },
2555 }
2556}
2557
2558#[inline]
2562pub fn slice_array(view: &V2TypedArrayView, start: u32, end: u32) -> *mut u8 {
2563 copy_range_to_new_array(view, start, end)
2564}
2565
2566#[inline]
2568pub fn take_array(view: &V2TypedArrayView, n: u32) -> *mut u8 {
2569 copy_range_to_new_array(view, 0, n)
2570}
2571
2572#[inline]
2576pub fn drop_array_n(view: &V2TypedArrayView, n: u32) -> *mut u8 {
2577 copy_range_to_new_array(view, n, view.len)
2578}
2579
2580#[inline]
2610pub fn native_kind_to_v2_elem_type(kind: NativeKind) -> Option<V2ElemType> {
2611 match kind {
2612 NativeKind::Float64 => Some(V2ElemType::F64),
2613 NativeKind::Int64 => Some(V2ElemType::I64),
2614 NativeKind::Int32 => Some(V2ElemType::I32),
2615 NativeKind::Bool => Some(V2ElemType::Bool),
2616 NativeKind::Int8 => Some(V2ElemType::I8),
2617 NativeKind::UInt8 => Some(V2ElemType::U8),
2618 NativeKind::Int16 => Some(V2ElemType::I16),
2619 NativeKind::UInt16 => Some(V2ElemType::U16),
2620 NativeKind::UInt32 => Some(V2ElemType::U32),
2621 NativeKind::Float32 => Some(V2ElemType::F32),
2622 NativeKind::Char => Some(V2ElemType::Char),
2623 NativeKind::StringV2 => Some(V2ElemType::String),
2624 NativeKind::DecimalV2 => Some(V2ElemType::Decimal),
2625 NativeKind::Ptr(HeapKind::TypedObject) => Some(V2ElemType::TypedObject),
2626 _ => None,
2627 }
2628}
2629
2630pub fn allocate_empty_typed_array(elem_type: V2ElemType, capacity: u32) -> *mut u8 {
2642 unsafe {
2643 let p: *mut u8 = match elem_type {
2644 V2ElemType::F64 => TypedArray::<f64>::with_capacity(capacity) as *mut u8,
2645 V2ElemType::I64 => TypedArray::<i64>::with_capacity(capacity) as *mut u8,
2646 V2ElemType::I32 => TypedArray::<i32>::with_capacity(capacity) as *mut u8,
2647 V2ElemType::Bool => TypedArray::<u8>::with_capacity(capacity) as *mut u8,
2648 V2ElemType::I8 => TypedArray::<i8>::with_capacity(capacity) as *mut u8,
2649 V2ElemType::U8 => TypedArray::<u8>::with_capacity(capacity) as *mut u8,
2650 V2ElemType::I16 => TypedArray::<i16>::with_capacity(capacity) as *mut u8,
2651 V2ElemType::U16 => TypedArray::<u16>::with_capacity(capacity) as *mut u8,
2652 V2ElemType::U32 => TypedArray::<u32>::with_capacity(capacity) as *mut u8,
2653 V2ElemType::F32 => TypedArray::<f32>::with_capacity(capacity) as *mut u8,
2654 V2ElemType::Char => TypedArray::<char>::with_capacity(capacity) as *mut u8,
2655 V2ElemType::String => {
2656 TypedArray::<*const StringObj>::with_capacity(capacity) as *mut u8
2657 }
2658 V2ElemType::Decimal => {
2659 TypedArray::<*const DecimalObj>::with_capacity(capacity) as *mut u8
2660 }
2661 V2ElemType::TypedObject => {
2662 TypedArray::<*const TypedObjectStorage>::with_capacity(capacity) as *mut u8
2663 }
2664 };
2665 let stamp_byte: u8 = match elem_type {
2666 V2ElemType::F64 => ELEM_TYPE_F64,
2667 V2ElemType::I64 => ELEM_TYPE_I64,
2668 V2ElemType::I32 => ELEM_TYPE_I32,
2669 V2ElemType::Bool => ELEM_TYPE_BOOL,
2670 V2ElemType::I8 => ELEM_TYPE_I8,
2671 V2ElemType::U8 => ELEM_TYPE_U8,
2672 V2ElemType::I16 => ELEM_TYPE_I16,
2673 V2ElemType::U16 => ELEM_TYPE_U16,
2674 V2ElemType::U32 => ELEM_TYPE_U32,
2675 V2ElemType::F32 => ELEM_TYPE_F32,
2676 V2ElemType::Char => ELEM_TYPE_CHAR,
2677 V2ElemType::String => ELEM_TYPE_STRING,
2678 V2ElemType::Decimal => ELEM_TYPE_DECIMAL,
2679 V2ElemType::TypedObject => ELEM_TYPE_TYPED_OBJECT,
2680 };
2681 stamp_elem_type(p, stamp_byte);
2682 p
2683 }
2684}
2685
2686#[inline]
2761pub fn eq_element(a_bits: u64, b_bits: u64, elem_type: V2ElemType) -> bool {
2762 match elem_type {
2763 V2ElemType::F64 => a_bits == b_bits,
2769 V2ElemType::I64 => a_bits == b_bits,
2770 V2ElemType::I32 => a_bits == b_bits,
2771 V2ElemType::Bool => a_bits == b_bits,
2772 V2ElemType::I8 => a_bits == b_bits,
2773 V2ElemType::U8 => a_bits == b_bits,
2774 V2ElemType::I16 => a_bits == b_bits,
2775 V2ElemType::U16 => a_bits == b_bits,
2776 V2ElemType::U32 => a_bits == b_bits,
2777 V2ElemType::F32 => a_bits == b_bits,
2778 V2ElemType::Char => a_bits == b_bits,
2779 V2ElemType::String => {
2781 if a_bits == 0 || b_bits == 0 {
2782 return a_bits == b_bits;
2783 }
2784 let a_ptr = a_bits as usize as *const StringObj;
2785 let b_ptr = b_bits as usize as *const StringObj;
2786 if a_ptr == b_ptr {
2787 return true;
2788 }
2789 unsafe { StringObj::as_str(a_ptr) == StringObj::as_str(b_ptr) }
2790 }
2791 V2ElemType::Decimal => {
2792 if a_bits == 0 || b_bits == 0 {
2793 return a_bits == b_bits;
2794 }
2795 let a_ptr = a_bits as usize as *const DecimalObj;
2796 let b_ptr = b_bits as usize as *const DecimalObj;
2797 if a_ptr == b_ptr {
2798 return true;
2799 }
2800 unsafe { DecimalObj::value(a_ptr) == DecimalObj::value(b_ptr) }
2801 }
2802 V2ElemType::TypedObject => {
2803 if a_bits == 0 || b_bits == 0 {
2804 return a_bits == b_bits;
2805 }
2806 let a_ptr = a_bits as usize as *const TypedObjectStorage;
2807 let b_ptr = b_bits as usize as *const TypedObjectStorage;
2808 if a_ptr == b_ptr {
2809 return true;
2810 }
2811 unsafe { typed_object_deep_eq(&*a_ptr, &*b_ptr) }
2818 }
2819 }
2820}
2821
2822unsafe fn typed_object_deep_eq(
2844 a: &TypedObjectStorage,
2845 b: &TypedObjectStorage,
2846) -> bool {
2847 if a.schema_id != b.schema_id {
2848 return false;
2849 }
2850 if a.slots.len() != b.slots.len() {
2851 return false;
2852 }
2853 if a.field_kinds.len() != b.field_kinds.len() {
2857 return false;
2858 }
2859 for (k1, k2) in a.field_kinds.iter().zip(b.field_kinds.iter()) {
2860 if k1 != k2 {
2861 return false;
2862 }
2863 }
2864 for i in 0..a.slots.len() {
2865 let bits_a = a.slots[i].raw();
2866 let bits_b = b.slots[i].raw();
2867 let kind = a.field_kinds[i];
2868 let field_elem = match kind {
2876 NativeKind::Float64 => Some(V2ElemType::F64),
2877 NativeKind::Int64 => Some(V2ElemType::I64),
2878 NativeKind::Int32 => Some(V2ElemType::I32),
2879 NativeKind::Int16 => Some(V2ElemType::I16),
2880 NativeKind::Int8 => Some(V2ElemType::I8),
2881 NativeKind::UInt8 => Some(V2ElemType::U8),
2882 NativeKind::UInt16 => Some(V2ElemType::U16),
2883 NativeKind::UInt32 => Some(V2ElemType::U32),
2884 NativeKind::Float32 => Some(V2ElemType::F32),
2885 NativeKind::Char => Some(V2ElemType::Char),
2886 NativeKind::Bool => Some(V2ElemType::Bool),
2887 NativeKind::StringV2 => Some(V2ElemType::String),
2888 NativeKind::DecimalV2 => Some(V2ElemType::Decimal),
2889 NativeKind::Ptr(HeapKind::TypedObject) => Some(V2ElemType::TypedObject),
2890 NativeKind::Null => {
2894 if bits_a != bits_b {
2895 return false;
2896 }
2897 continue;
2898 }
2899 NativeKind::String => {
2904 if bits_a == bits_b {
2905 continue;
2906 }
2907 if bits_a == 0 || bits_b == 0 {
2908 return false;
2909 }
2910 let s_a = unsafe { &*(bits_a as usize as *const String) };
2911 let s_b = unsafe { &*(bits_b as usize as *const String) };
2912 if s_a != s_b {
2913 return false;
2914 }
2915 continue;
2916 }
2917 _ => {
2925 if bits_a != bits_b {
2926 return false;
2927 }
2928 continue;
2929 }
2930 };
2931 if let Some(et) = field_elem {
2932 if !eq_element(bits_a, bits_b, et) {
2933 return false;
2934 }
2935 }
2936 }
2937 true
2938}
2939
2940#[inline]
2958pub fn position_of(view: &V2TypedArrayView, needle_bits: u64) -> Option<u32> {
2959 let n = view.len;
2960 if n == 0 {
2961 return None;
2962 }
2963 macro_rules! scan_scalar {
2967 ($t:ty, $to_bits:expr) => {{
2968 let arr = view.ptr as *const TypedArray<$t>;
2969 for i in 0..n {
2970 let v = unsafe { TypedArray::<$t>::get_unchecked(arr, i) };
2971 if $to_bits(v) == needle_bits {
2972 return Some(i);
2973 }
2974 }
2975 None
2976 }};
2977 }
2978 match view.elem_type {
2979 V2ElemType::F64 => scan_scalar!(f64, |v: f64| v.to_bits()),
2980 V2ElemType::I64 => scan_scalar!(i64, |v: i64| v as u64),
2981 V2ElemType::I32 => scan_scalar!(i32, |v: i32| (v as i64) as u64),
2982 V2ElemType::Bool => scan_scalar!(u8, |v: u8| (v != 0) as u64),
2983 V2ElemType::I8 => scan_scalar!(i8, |v: i8| (v as i64) as u64),
2984 V2ElemType::U8 => scan_scalar!(u8, |v: u8| v as u64),
2985 V2ElemType::I16 => scan_scalar!(i16, |v: i16| (v as i64) as u64),
2986 V2ElemType::U16 => scan_scalar!(u16, |v: u16| v as u64),
2987 V2ElemType::U32 => scan_scalar!(u32, |v: u32| v as u64),
2988 V2ElemType::F32 => scan_scalar!(f32, |v: f32| v.to_bits() as u64),
2989 V2ElemType::Char => scan_scalar!(char, |v: char| v as u32 as u64),
2990 V2ElemType::String => unsafe {
2991 let arr = view.ptr as *const TypedArray<*const StringObj>;
2992 for i in 0..n {
2993 let elem_ptr = TypedArray::<*const StringObj>::get_unchecked(arr, i);
2994 if eq_element(elem_ptr as u64, needle_bits, V2ElemType::String) {
2995 return Some(i);
2996 }
2997 }
2998 None
2999 },
3000 V2ElemType::Decimal => unsafe {
3001 let arr = view.ptr as *const TypedArray<*const DecimalObj>;
3002 for i in 0..n {
3003 let elem_ptr = TypedArray::<*const DecimalObj>::get_unchecked(arr, i);
3004 if eq_element(elem_ptr as u64, needle_bits, V2ElemType::Decimal) {
3005 return Some(i);
3006 }
3007 }
3008 None
3009 },
3010 V2ElemType::TypedObject => unsafe {
3011 let arr = view.ptr as *const TypedArray<*const TypedObjectStorage>;
3012 for i in 0..n {
3013 let elem_ptr = TypedArray::<*const TypedObjectStorage>::get_unchecked(arr, i);
3014 if eq_element(elem_ptr as u64, needle_bits, V2ElemType::TypedObject) {
3015 return Some(i);
3016 }
3017 }
3018 None
3019 }
3020 }
3021}
3022
3023#[inline]
3068pub fn cmp_element_natural(
3069 view: &V2TypedArrayView,
3070 bits_a: u64,
3071 bits_b: u64,
3072) -> Option<std::cmp::Ordering> {
3073 use std::cmp::Ordering;
3074 match view.elem_type {
3075 V2ElemType::F64 => Some(f64::from_bits(bits_a).total_cmp(&f64::from_bits(bits_b))),
3076 V2ElemType::F32 => Some(
3077 f32::from_bits(bits_a as u32).total_cmp(&f32::from_bits(bits_b as u32)),
3078 ),
3079 V2ElemType::I64 => Some((bits_a as i64).cmp(&(bits_b as i64))),
3080 V2ElemType::I32 => Some((bits_a as u32 as i32).cmp(&(bits_b as u32 as i32))),
3081 V2ElemType::I16 => Some((bits_a as u16 as i16).cmp(&(bits_b as u16 as i16))),
3082 V2ElemType::I8 => Some((bits_a as u8 as i8).cmp(&(bits_b as u8 as i8))),
3083 V2ElemType::U32 => Some((bits_a as u32).cmp(&(bits_b as u32))),
3084 V2ElemType::U16 => Some((bits_a as u16).cmp(&(bits_b as u16))),
3085 V2ElemType::U8 => Some((bits_a as u8).cmp(&(bits_b as u8))),
3086 V2ElemType::Bool => {
3087 let a = bits_a != 0;
3090 let b = bits_b != 0;
3091 Some(a.cmp(&b))
3092 }
3093 V2ElemType::Char => {
3094 Some((bits_a as u32).cmp(&(bits_b as u32)))
3098 }
3099 V2ElemType::String => unsafe {
3100 let a_ptr = bits_a as usize as *const StringObj;
3101 let b_ptr = bits_b as usize as *const StringObj;
3102 if a_ptr.is_null() || b_ptr.is_null() {
3103 return None;
3104 }
3105 let a = StringObj::as_str(a_ptr);
3106 let b = StringObj::as_str(b_ptr);
3107 Some(a.cmp(b))
3108 },
3109 V2ElemType::Decimal => unsafe {
3110 let a_ptr = bits_a as usize as *const DecimalObj;
3111 let b_ptr = bits_b as usize as *const DecimalObj;
3112 if a_ptr.is_null() || b_ptr.is_null() {
3113 return None;
3114 }
3115 let a = DecimalObj::value(a_ptr);
3116 let b = DecimalObj::value(b_ptr);
3117 Some(a.cmp(&b))
3118 },
3119 V2ElemType::TypedObject => {
3120 None
3126 }
3127 _ => {
3128 #[allow(unreachable_patterns)]
3131 None
3132 }
3133 }
3134}
3135
3136pub fn permute_array(view: &V2TypedArrayView, indices: &[u32]) -> *mut u8 {
3153 let out_len = indices.len() as u32;
3154
3155 #[inline]
3165 unsafe fn permute_scalar<T: Copy>(
3166 src_data: *const T,
3167 dst_data: *mut T,
3168 src_len: u32,
3169 indices: &[u32],
3170 ) -> u32 {
3171 if src_data.is_null() || dst_data.is_null() {
3172 return 0;
3173 }
3174 let mut w: u32 = 0;
3175 for &idx in indices {
3176 if idx >= src_len {
3177 continue;
3178 }
3179 unsafe {
3180 let v = *src_data.add(idx as usize);
3181 *dst_data.add(w as usize) = v;
3182 }
3183 w += 1;
3184 }
3185 w
3186 }
3187
3188 match view.elem_type {
3189 V2ElemType::F64 => unsafe {
3190 let new_arr = TypedArray::<f64>::with_capacity(out_len);
3191 let src = view.ptr as *const TypedArray<f64>;
3192 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3193 (*new_arr).len = written;
3194 let p = new_arr as *mut u8;
3195 stamp_elem_type(p, ELEM_TYPE_F64);
3196 p
3197 },
3198 V2ElemType::I64 => unsafe {
3199 let new_arr = TypedArray::<i64>::with_capacity(out_len);
3200 let src = view.ptr as *const TypedArray<i64>;
3201 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3202 (*new_arr).len = written;
3203 let p = new_arr as *mut u8;
3204 stamp_elem_type(p, ELEM_TYPE_I64);
3205 p
3206 },
3207 V2ElemType::I32 => unsafe {
3208 let new_arr = TypedArray::<i32>::with_capacity(out_len);
3209 let src = view.ptr as *const TypedArray<i32>;
3210 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3211 (*new_arr).len = written;
3212 let p = new_arr as *mut u8;
3213 stamp_elem_type(p, ELEM_TYPE_I32);
3214 p
3215 },
3216 V2ElemType::Bool => unsafe {
3217 let new_arr = TypedArray::<u8>::with_capacity(out_len);
3218 let src = view.ptr as *const TypedArray<u8>;
3219 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3220 (*new_arr).len = written;
3221 let p = new_arr as *mut u8;
3222 stamp_elem_type(p, ELEM_TYPE_BOOL);
3223 p
3224 },
3225 V2ElemType::I8 => unsafe {
3226 let new_arr = TypedArray::<i8>::with_capacity(out_len);
3227 let src = view.ptr as *const TypedArray<i8>;
3228 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3229 (*new_arr).len = written;
3230 let p = new_arr as *mut u8;
3231 stamp_elem_type(p, ELEM_TYPE_I8);
3232 p
3233 },
3234 V2ElemType::U8 => unsafe {
3235 let new_arr = TypedArray::<u8>::with_capacity(out_len);
3236 let src = view.ptr as *const TypedArray<u8>;
3237 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3238 (*new_arr).len = written;
3239 let p = new_arr as *mut u8;
3240 stamp_elem_type(p, ELEM_TYPE_U8);
3241 p
3242 },
3243 V2ElemType::I16 => unsafe {
3244 let new_arr = TypedArray::<i16>::with_capacity(out_len);
3245 let src = view.ptr as *const TypedArray<i16>;
3246 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3247 (*new_arr).len = written;
3248 let p = new_arr as *mut u8;
3249 stamp_elem_type(p, ELEM_TYPE_I16);
3250 p
3251 },
3252 V2ElemType::U16 => unsafe {
3253 let new_arr = TypedArray::<u16>::with_capacity(out_len);
3254 let src = view.ptr as *const TypedArray<u16>;
3255 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3256 (*new_arr).len = written;
3257 let p = new_arr as *mut u8;
3258 stamp_elem_type(p, ELEM_TYPE_U16);
3259 p
3260 },
3261 V2ElemType::U32 => unsafe {
3262 let new_arr = TypedArray::<u32>::with_capacity(out_len);
3263 let src = view.ptr as *const TypedArray<u32>;
3264 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3265 (*new_arr).len = written;
3266 let p = new_arr as *mut u8;
3267 stamp_elem_type(p, ELEM_TYPE_U32);
3268 p
3269 },
3270 V2ElemType::F32 => unsafe {
3271 let new_arr = TypedArray::<f32>::with_capacity(out_len);
3272 let src = view.ptr as *const TypedArray<f32>;
3273 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3274 (*new_arr).len = written;
3275 let p = new_arr as *mut u8;
3276 stamp_elem_type(p, ELEM_TYPE_F32);
3277 p
3278 },
3279 V2ElemType::Char => unsafe {
3280 let new_arr = TypedArray::<char>::with_capacity(out_len);
3281 let src = view.ptr as *const TypedArray<char>;
3282 let written = permute_scalar((*src).data, (*new_arr).data, view.len, indices);
3283 (*new_arr).len = written;
3284 let p = new_arr as *mut u8;
3285 stamp_elem_type(p, ELEM_TYPE_CHAR);
3286 p
3287 },
3288 V2ElemType::String => unsafe {
3289 let new_arr = TypedArray::<*const StringObj>::with_capacity(out_len);
3290 let src = view.ptr as *const TypedArray<*const StringObj>;
3291 let src_data = (*src).data;
3292 let dst_data = (*new_arr).data;
3293 let mut w: u32 = 0;
3294 if !src_data.is_null() && !dst_data.is_null() {
3295 for &idx in indices {
3296 if idx >= view.len {
3297 continue;
3298 }
3299 let elem = *src_data.add(idx as usize);
3300 v2_retain(&(*elem).header);
3301 *dst_data.add(w as usize) = elem;
3302 w += 1;
3303 }
3304 }
3305 (*new_arr).len = w;
3306 let p = new_arr as *mut u8;
3307 stamp_elem_type(p, ELEM_TYPE_STRING);
3308 p
3309 },
3310 V2ElemType::Decimal => unsafe {
3311 let new_arr = TypedArray::<*const DecimalObj>::with_capacity(out_len);
3312 let src = view.ptr as *const TypedArray<*const DecimalObj>;
3313 let src_data = (*src).data;
3314 let dst_data = (*new_arr).data;
3315 let mut w: u32 = 0;
3316 if !src_data.is_null() && !dst_data.is_null() {
3317 for &idx in indices {
3318 if idx >= view.len {
3319 continue;
3320 }
3321 let elem = *src_data.add(idx as usize);
3322 v2_retain(&(*elem).header);
3323 *dst_data.add(w as usize) = elem;
3324 w += 1;
3325 }
3326 }
3327 (*new_arr).len = w;
3328 let p = new_arr as *mut u8;
3329 stamp_elem_type(p, ELEM_TYPE_DECIMAL);
3330 p
3331 },
3332 V2ElemType::TypedObject => unsafe {
3333 let new_arr =
3334 TypedArray::<*const TypedObjectStorage>::with_capacity(out_len);
3335 let src = view.ptr as *const TypedArray<*const TypedObjectStorage>;
3336 let src_data = (*src).data;
3337 let dst_data = (*new_arr).data;
3338 let mut w: u32 = 0;
3339 if !src_data.is_null() && !dst_data.is_null() {
3340 for &idx in indices {
3341 if idx >= view.len {
3342 continue;
3343 }
3344 let elem = *src_data.add(idx as usize);
3345 v2_retain(&(*elem).header);
3346 *dst_data.add(w as usize) = elem;
3347 w += 1;
3348 }
3349 }
3350 (*new_arr).len = w;
3351 let p = new_arr as *mut u8;
3352 stamp_elem_type(p, ELEM_TYPE_TYPED_OBJECT);
3353 p
3354 },
3355 }
3356}
3357
3358#[inline]
3366pub fn contains_element(view: &V2TypedArrayView, needle_bits: u64) -> bool {
3367 position_of(view, needle_bits).is_some()
3368}
3369
3370#[cfg(test)]
3371mod tests {
3372 use super::*;
3373
3374 #[inline]
3378 fn ptr_pair(ptr: *mut u8) -> (u64, NativeKind) {
3379 (ptr as usize as u64, NativeKind::Ptr(HeapKind::TypedArray))
3380 }
3381
3382 #[test]
3383 fn test_stamp_and_read_elem_type_f64() {
3384 let arr = TypedArray::<f64>::with_capacity(0);
3385 unsafe {
3386 stamp_elem_type(arr as *mut u8, ELEM_TYPE_F64);
3387 let byte = read_elem_type_byte(arr as *const u8);
3388 assert_eq!(byte, ELEM_TYPE_F64);
3389 TypedArray::drop_array(arr);
3390 }
3391 }
3392
3393 #[test]
3394 fn test_as_v2_typed_array_recognizes_stamped_f64() {
3395 let arr = TypedArray::<f64>::with_capacity(4);
3396 unsafe {
3397 TypedArray::push(arr, 1.5);
3398 TypedArray::push(arr, 2.5);
3399 stamp_elem_type(arr as *mut u8, ELEM_TYPE_F64);
3400 }
3401 let (bits, kind) = ptr_pair(arr as *mut u8);
3402 let view = as_v2_typed_array(bits, kind).expect("should recognize v2 typed array");
3403 assert_eq!(view.elem_type, V2ElemType::F64);
3404 assert_eq!(view.len, 2);
3405 unsafe {
3406 TypedArray::drop_array(arr);
3407 }
3408 }
3409
3410 #[test]
3411 fn test_read_element_i64_indices() {
3412 let arr = TypedArray::<i64>::from_slice(&[10, 20, 30]);
3413 unsafe {
3414 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3415 }
3416 let (bits, kind) = ptr_pair(arr as *mut u8);
3417 let view = as_v2_typed_array(bits, kind).unwrap();
3418 assert_eq!(read_element(&view, 0), Some((10u64, NativeKind::Int64)));
3419 assert_eq!(read_element(&view, 1), Some((20u64, NativeKind::Int64)));
3420 assert_eq!(read_element(&view, 2), Some((30u64, NativeKind::Int64)));
3421 assert!(read_element(&view, 3).is_none());
3422 unsafe {
3423 TypedArray::drop_array(arr);
3424 }
3425 }
3426
3427 #[test]
3428 fn test_clone_array_i64() {
3429 let arr = TypedArray::<i64>::from_slice(&[100, 200, 300]);
3430 unsafe {
3431 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3432 }
3433 let (bits, kind) = ptr_pair(arr as *mut u8);
3434 let view = as_v2_typed_array(bits, kind).unwrap();
3435 let cloned_ptr = clone_array(&view);
3436 let (cb, ck) = ptr_pair(cloned_ptr);
3437 let cloned_view = as_v2_typed_array(cb, ck).expect("clone should be detectable");
3438 assert_eq!(cloned_view.elem_type, V2ElemType::I64);
3439 assert_eq!(cloned_view.len, 3);
3440 assert_eq!(read_element(&cloned_view, 0), Some((100u64, NativeKind::Int64)));
3441 unsafe {
3442 TypedArray::<i64>::drop_array(cloned_ptr as *mut TypedArray<i64>);
3443 TypedArray::drop_array(arr);
3444 }
3445 }
3446
3447 #[test]
3452 fn test_stamp_and_read_elem_type_f32_char() {
3453 let arr_f32 = TypedArray::<f32>::with_capacity(0);
3454 let arr_char = TypedArray::<char>::with_capacity(0);
3455 unsafe {
3456 stamp_elem_type(arr_f32 as *mut u8, ELEM_TYPE_F32);
3457 stamp_elem_type(arr_char as *mut u8, ELEM_TYPE_CHAR);
3458 assert_eq!(read_elem_type_byte(arr_f32 as *const u8), ELEM_TYPE_F32);
3459 assert_eq!(read_elem_type_byte(arr_char as *const u8), ELEM_TYPE_CHAR);
3460 TypedArray::drop_array(arr_f32);
3461 TypedArray::drop_array(arr_char);
3462 }
3463 }
3464
3465 #[test]
3466 fn test_as_v2_typed_array_recognizes_stamped_f32() {
3467 let arr = TypedArray::<f32>::with_capacity(4);
3468 unsafe {
3469 TypedArray::push(arr, 1.5_f32);
3470 TypedArray::push(arr, 2.5_f32);
3471 stamp_elem_type(arr as *mut u8, ELEM_TYPE_F32);
3472 }
3473 let (bits, kind) = ptr_pair(arr as *mut u8);
3474 let view = as_v2_typed_array(bits, kind).expect("should recognize v2 typed array");
3475 assert_eq!(view.elem_type, V2ElemType::F32);
3476 assert_eq!(view.len, 2);
3477 unsafe { TypedArray::drop_array(arr); }
3478 }
3479
3480 #[test]
3481 fn test_as_v2_typed_array_recognizes_stamped_char() {
3482 let arr = TypedArray::<char>::with_capacity(4);
3483 unsafe {
3484 TypedArray::push(arr, 'A');
3485 TypedArray::push(arr, '☃');
3486 stamp_elem_type(arr as *mut u8, ELEM_TYPE_CHAR);
3487 }
3488 let (bits, kind) = ptr_pair(arr as *mut u8);
3489 let view = as_v2_typed_array(bits, kind).expect("should recognize v2 typed array");
3490 assert_eq!(view.elem_type, V2ElemType::Char);
3491 assert_eq!(view.len, 2);
3492 unsafe { TypedArray::drop_array(arr); }
3493 }
3494
3495 #[test]
3496 fn test_read_element_f32() {
3497 let arr = TypedArray::<f32>::from_slice(&[1.5_f32, 2.25_f32, 3.0_f32]);
3498 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_F32); }
3499 let (bits, kind) = ptr_pair(arr as *mut u8);
3500 let view = as_v2_typed_array(bits, kind).unwrap();
3501 let r0 = read_element(&view, 0).unwrap();
3502 let r1 = read_element(&view, 1).unwrap();
3503 let r2 = read_element(&view, 2).unwrap();
3504 assert_eq!(r0.1, NativeKind::Float32);
3505 assert_eq!(f32::from_bits(r0.0 as u32), 1.5_f32);
3506 assert_eq!(f32::from_bits(r1.0 as u32), 2.25_f32);
3507 assert_eq!(f32::from_bits(r2.0 as u32), 3.0_f32);
3508 assert!(read_element(&view, 3).is_none());
3509 unsafe { TypedArray::drop_array(arr); }
3510 }
3511
3512 #[test]
3513 fn test_read_element_char() {
3514 let arr = TypedArray::<char>::from_slice(&['h', 'i', '!']);
3515 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_CHAR); }
3516 let (bits, kind) = ptr_pair(arr as *mut u8);
3517 let view = as_v2_typed_array(bits, kind).unwrap();
3518 for (i, expected) in ['h', 'i', '!'].iter().enumerate() {
3519 let (b, k) = read_element(&view, i as u32).unwrap();
3520 assert_eq!(k, NativeKind::Char);
3521 assert_eq!(char::from_u32(b as u32).unwrap(), *expected);
3522 }
3523 assert!(read_element(&view, 3).is_none());
3524 unsafe { TypedArray::drop_array(arr); }
3525 }
3526
3527 #[test]
3528 fn test_push_element_f32() {
3529 let arr = TypedArray::<f32>::with_capacity(4);
3530 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_F32); }
3531 let (bits, kind) = ptr_pair(arr as *mut u8);
3532 let view = as_v2_typed_array(bits, kind).unwrap();
3533 push_element(&view, (1.5_f32).to_bits() as u64, NativeKind::Float32).unwrap();
3534 let view = as_v2_typed_array(bits, kind).unwrap();
3536 let (b, k) = read_element(&view, 0).unwrap();
3537 assert_eq!(k, NativeKind::Float32);
3538 assert_eq!(f32::from_bits(b as u32), 1.5_f32);
3539 unsafe { TypedArray::drop_array(arr); }
3540 }
3541
3542 #[test]
3543 fn test_push_element_char() {
3544 let arr = TypedArray::<char>::with_capacity(4);
3545 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_CHAR); }
3546 let (bits, kind) = ptr_pair(arr as *mut u8);
3547 let view = as_v2_typed_array(bits, kind).unwrap();
3548 push_element(&view, 'Z' as u32 as u64, NativeKind::Char).unwrap();
3549 let view = as_v2_typed_array(bits, kind).unwrap();
3550 let (b, _) = read_element(&view, 0).unwrap();
3551 assert_eq!(char::from_u32(b as u32).unwrap(), 'Z');
3552 unsafe { TypedArray::drop_array(arr); }
3553 }
3554
3555 #[test]
3556 fn test_clone_array_f32() {
3557 let arr = TypedArray::<f32>::from_slice(&[1.0_f32, 2.0_f32, 3.0_f32]);
3558 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_F32); }
3559 let (bits, kind) = ptr_pair(arr as *mut u8);
3560 let view = as_v2_typed_array(bits, kind).unwrap();
3561 let cloned = clone_array(&view);
3562 let (cb, ck) = ptr_pair(cloned);
3563 let cv = as_v2_typed_array(cb, ck).unwrap();
3564 assert_eq!(cv.elem_type, V2ElemType::F32);
3565 assert_eq!(cv.len, 3);
3566 unsafe {
3567 TypedArray::<f32>::drop_array(cloned as *mut TypedArray<f32>);
3568 TypedArray::drop_array(arr);
3569 }
3570 }
3571
3572 #[test]
3573 fn test_clone_array_char() {
3574 let arr = TypedArray::<char>::from_slice(&['a', 'b', 'c']);
3575 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_CHAR); }
3576 let (bits, kind) = ptr_pair(arr as *mut u8);
3577 let view = as_v2_typed_array(bits, kind).unwrap();
3578 let cloned = clone_array(&view);
3579 let (cb, ck) = ptr_pair(cloned);
3580 let cv = as_v2_typed_array(cb, ck).unwrap();
3581 assert_eq!(cv.elem_type, V2ElemType::Char);
3582 assert_eq!(cv.len, 3);
3583 unsafe {
3584 TypedArray::<char>::drop_array(cloned as *mut TypedArray<char>);
3585 TypedArray::drop_array(arr);
3586 }
3587 }
3588
3589 #[test]
3590 fn test_non_pointer_value_returns_none() {
3591 assert!(as_v2_typed_array(42u64, NativeKind::Int64).is_none());
3593
3594 assert!(as_v2_typed_array(3.14_f64.to_bits(), NativeKind::Float64).is_none());
3596
3597 assert!(as_v2_typed_array(1u64, NativeKind::Bool).is_none());
3599
3600 assert!(as_v2_typed_array(u64::MAX, NativeKind::UInt64).is_none());
3606 assert!(as_v2_typed_array(1000u64, NativeKind::UInt64).is_none());
3607 assert!(as_v2_typed_array(0u64, NativeKind::UInt64).is_none());
3608
3609 assert!(
3611 as_v2_typed_array(0u64, NativeKind::Ptr(HeapKind::TypedArray)).is_none()
3612 );
3613 }
3614
3615 #[test]
3622 fn test_kind_track_discriminates_array_carrier_from_scalar() {
3623 let arr = TypedArray::<i64>::from_slice(&[100, 200]);
3624 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64) };
3625 let bits = arr as usize as u64;
3626
3627 let view = as_v2_typed_array(bits, NativeKind::Ptr(HeapKind::TypedArray))
3629 .expect("array carrier kind must detect the typed array");
3630 assert_eq!(view.elem_type, V2ElemType::I64);
3631 assert_eq!(view.len, 2);
3632
3633 assert!(
3635 as_v2_typed_array(bits, NativeKind::UInt64).is_none(),
3636 "a scalar-u64 kind must NOT be treated as the array carrier"
3637 );
3638
3639 unsafe { TypedArray::<i64>::drop_array(arr) };
3640 }
3641
3642 #[test]
3651 fn test_stamp_and_read_elem_type_string_decimal() {
3652 let arr_string = TypedArray::<*const StringObj>::with_capacity(0);
3653 let arr_decimal = TypedArray::<*const DecimalObj>::with_capacity(0);
3654 unsafe {
3655 stamp_elem_type(arr_string as *mut u8, ELEM_TYPE_STRING);
3656 stamp_elem_type(arr_decimal as *mut u8, ELEM_TYPE_DECIMAL);
3657 assert_eq!(read_elem_type_byte(arr_string as *const u8), ELEM_TYPE_STRING);
3658 assert_eq!(read_elem_type_byte(arr_decimal as *const u8), ELEM_TYPE_DECIMAL);
3659 TypedArray::<*const StringObj>::drop_array_heap(arr_string);
3660 TypedArray::<*const DecimalObj>::drop_array_heap(arr_decimal);
3661 }
3662 }
3663
3664 #[test]
3665 fn test_as_v2_typed_array_recognizes_stamped_string() {
3666 let arr = TypedArray::<*const StringObj>::with_capacity(4);
3667 unsafe {
3668 let s = StringObj::new("hello");
3669 TypedArray::push(arr, s as *const StringObj);
3670 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
3671 }
3672 let (bits, kind) = ptr_pair(arr as *mut u8);
3673 let view = as_v2_typed_array(bits, kind).expect("should recognize v2 typed array");
3674 assert_eq!(view.elem_type, V2ElemType::String);
3675 assert_eq!(view.len, 1);
3676 unsafe { TypedArray::<*const StringObj>::drop_array_heap(arr); }
3677 }
3678
3679 #[test]
3680 fn test_as_v2_typed_array_recognizes_stamped_decimal() {
3681 use rust_decimal::Decimal;
3682 use rust_decimal::prelude::FromPrimitive;
3683 let arr = TypedArray::<*const DecimalObj>::with_capacity(4);
3684 unsafe {
3685 let d = DecimalObj::new(Decimal::from_f64(3.14).unwrap());
3686 TypedArray::push(arr, d as *const DecimalObj);
3687 stamp_elem_type(arr as *mut u8, ELEM_TYPE_DECIMAL);
3688 }
3689 let (bits, kind) = ptr_pair(arr as *mut u8);
3690 let view = as_v2_typed_array(bits, kind).expect("should recognize v2 typed array");
3691 assert_eq!(view.elem_type, V2ElemType::Decimal);
3692 assert_eq!(view.len, 1);
3693 unsafe { TypedArray::<*const DecimalObj>::drop_array_heap(arr); }
3694 }
3695
3696 #[test]
3697 fn test_read_element_string_retains_share() {
3698 use shape_value::v2::refcount::v2_get_refcount;
3699 unsafe {
3700 let arr = TypedArray::<*const StringObj>::with_capacity(4);
3701 let s = StringObj::new("greetings");
3702 assert_eq!(v2_get_refcount(&(*s).header), 1);
3704 TypedArray::push(arr, s as *const StringObj);
3705 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
3706 let (bits, kind) = ptr_pair(arr as *mut u8);
3707 let view = as_v2_typed_array(bits, kind).unwrap();
3708 let (read_bits, read_kind) = read_element(&view, 0).unwrap();
3710 assert_eq!(read_kind, NativeKind::StringV2);
3711 assert_eq!(read_bits, s as u64);
3712 assert_eq!(v2_get_refcount(&(*s).header), 2);
3713 <StringObj as HeapElement>::release_elem(s);
3716 assert_eq!(v2_get_refcount(&(*s).header), 1);
3717 TypedArray::<*const StringObj>::drop_array_heap(arr);
3719 }
3720 }
3721
3722 #[test]
3723 fn test_read_element_decimal_retains_share() {
3724 use rust_decimal::Decimal;
3725 use rust_decimal::prelude::FromPrimitive;
3726 use shape_value::v2::refcount::v2_get_refcount;
3727 unsafe {
3728 let arr = TypedArray::<*const DecimalObj>::with_capacity(4);
3729 let d = DecimalObj::new(Decimal::from_f64(2.5).unwrap());
3730 assert_eq!(v2_get_refcount(&(*d).header), 1);
3731 TypedArray::push(arr, d as *const DecimalObj);
3732 stamp_elem_type(arr as *mut u8, ELEM_TYPE_DECIMAL);
3733 let (bits, kind) = ptr_pair(arr as *mut u8);
3734 let view = as_v2_typed_array(bits, kind).unwrap();
3735 let (read_bits, read_kind) = read_element(&view, 0).unwrap();
3736 assert_eq!(read_kind, NativeKind::DecimalV2);
3737 assert_eq!(read_bits, d as u64);
3738 assert_eq!(v2_get_refcount(&(*d).header), 2);
3739 <DecimalObj as HeapElement>::release_elem(d);
3740 assert_eq!(v2_get_refcount(&(*d).header), 1);
3741 TypedArray::<*const DecimalObj>::drop_array_heap(arr);
3742 }
3743 }
3744
3745 #[test]
3746 fn test_push_element_string_kind_mismatch_refused() {
3747 let arr = TypedArray::<*const StringObj>::with_capacity(4);
3753 unsafe { stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING); }
3754 let (bits, kind) = ptr_pair(arr as *mut u8);
3755 let view = as_v2_typed_array(bits, kind).unwrap();
3756 let result = push_element(&view, 0xDEAD_BEEF, NativeKind::String);
3759 assert!(result.is_err());
3760 let err = result.unwrap_err();
3761 assert!(err.contains("StringV2"), "expected error to cite StringV2, got: {}", err);
3762 unsafe { TypedArray::<*const StringObj>::drop_array_heap(arr); }
3763 }
3764
3765 #[test]
3766 fn test_clone_array_string_retains_each_element() {
3767 use shape_value::v2::refcount::v2_get_refcount;
3768 unsafe {
3769 let arr = TypedArray::<*const StringObj>::with_capacity(2);
3770 let s1 = StringObj::new("foo");
3771 let s2 = StringObj::new("bar");
3772 TypedArray::push(arr, s1 as *const StringObj);
3773 TypedArray::push(arr, s2 as *const StringObj);
3774 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
3775 assert_eq!(v2_get_refcount(&(*s1).header), 1);
3777 assert_eq!(v2_get_refcount(&(*s2).header), 1);
3778 let (bits, kind) = ptr_pair(arr as *mut u8);
3779 let view = as_v2_typed_array(bits, kind).unwrap();
3780 let cloned = clone_array(&view);
3781 assert_eq!(v2_get_refcount(&(*s1).header), 2);
3783 assert_eq!(v2_get_refcount(&(*s2).header), 2);
3784 let (cb, ck) = ptr_pair(cloned);
3785 let cv = as_v2_typed_array(cb, ck).unwrap();
3786 assert_eq!(cv.elem_type, V2ElemType::String);
3787 assert_eq!(cv.len, 2);
3788 TypedArray::<*const StringObj>::drop_array_heap(cloned as *mut TypedArray<*const StringObj>);
3790 assert_eq!(v2_get_refcount(&(*s1).header), 1);
3791 assert_eq!(v2_get_refcount(&(*s2).header), 1);
3792 TypedArray::<*const StringObj>::drop_array_heap(arr);
3794 }
3795 }
3796
3797 #[test]
3798 fn test_pop_element_string_transfers_share() {
3799 use shape_value::v2::refcount::v2_get_refcount;
3800 unsafe {
3801 let arr = TypedArray::<*const StringObj>::with_capacity(2);
3802 let s = StringObj::new("popme");
3803 TypedArray::push(arr, s as *const StringObj);
3804 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
3805 assert_eq!(v2_get_refcount(&(*s).header), 1);
3806 let (bits, kind) = ptr_pair(arr as *mut u8);
3807 let view = as_v2_typed_array(bits, kind).unwrap();
3808 let (popped_bits, popped_kind) = pop_element(&view).unwrap();
3810 assert_eq!(popped_kind, NativeKind::StringV2);
3811 assert_eq!(popped_bits, s as u64);
3812 assert_eq!(v2_get_refcount(&(*s).header), 1);
3814 <StringObj as HeapElement>::release_elem(s);
3816 TypedArray::<*const StringObj>::drop_array_heap(arr);
3817 }
3818 }
3819
3820 #[test]
3834 fn test_reverse_array_i64() {
3835 unsafe {
3836 let arr = TypedArray::<i64>::from_slice(&[1, 2, 3, 4, 5]);
3837 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3838 let (bits, kind) = ptr_pair(arr as *mut u8);
3839 let view = as_v2_typed_array(bits, kind).unwrap();
3840 let new_ptr = reverse_array(&view);
3841 let new_view =
3842 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3843 .unwrap();
3844 assert_eq!(new_view.elem_type, V2ElemType::I64);
3845 assert_eq!(new_view.len, 5);
3846 let new_arr = new_ptr as *const TypedArray<i64>;
3847 let data = (*new_arr).data;
3848 assert_eq!(*data.add(0), 5);
3849 assert_eq!(*data.add(1), 4);
3850 assert_eq!(*data.add(2), 3);
3851 assert_eq!(*data.add(3), 2);
3852 assert_eq!(*data.add(4), 1);
3853 TypedArray::<i64>::drop_array(arr);
3854 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
3855 }
3856 }
3857
3858 #[test]
3859 fn test_reverse_array_empty() {
3860 unsafe {
3861 let arr = TypedArray::<i64>::with_capacity(0);
3862 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3863 let (bits, kind) = ptr_pair(arr as *mut u8);
3864 let view = as_v2_typed_array(bits, kind).unwrap();
3865 let new_ptr = reverse_array(&view);
3866 let new_view =
3867 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3868 .unwrap();
3869 assert_eq!(new_view.len, 0);
3870 TypedArray::<i64>::drop_array(arr);
3871 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
3872 }
3873 }
3874
3875 #[test]
3876 fn test_reverse_array_string_retains_each_element() {
3877 use shape_value::v2::refcount::v2_get_refcount;
3878 unsafe {
3879 let s1 = StringObj::new("a");
3880 let s2 = StringObj::new("b");
3881 let arr = TypedArray::<*const StringObj>::with_capacity(2);
3882 TypedArray::push(arr, s1 as *const StringObj);
3883 TypedArray::push(arr, s2 as *const StringObj);
3884 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
3885 assert_eq!(v2_get_refcount(&(*s1).header), 1);
3886 assert_eq!(v2_get_refcount(&(*s2).header), 1);
3887
3888 let (bits, kind) = ptr_pair(arr as *mut u8);
3889 let view = as_v2_typed_array(bits, kind).unwrap();
3890 let new_ptr = reverse_array(&view);
3891
3892 assert_eq!(v2_get_refcount(&(*s1).header), 2);
3895 assert_eq!(v2_get_refcount(&(*s2).header), 2);
3896
3897 let new_view =
3898 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3899 .unwrap();
3900 assert_eq!(new_view.elem_type, V2ElemType::String);
3901 assert_eq!(new_view.len, 2);
3902 let new_arr = new_ptr as *const TypedArray<*const StringObj>;
3903 let data = (*new_arr).data;
3904 assert_eq!(*data.add(0), s2 as *const StringObj);
3905 assert_eq!(*data.add(1), s1 as *const StringObj);
3906
3907 TypedArray::<*const StringObj>::drop_array_heap(arr);
3908 TypedArray::<*const StringObj>::drop_array_heap(
3909 new_ptr as *mut TypedArray<*const StringObj>,
3910 );
3911 }
3913 }
3914
3915 #[test]
3916 fn test_concat_arrays_i64() {
3917 unsafe {
3918 let a = TypedArray::<i64>::from_slice(&[1, 2]);
3919 let b = TypedArray::<i64>::from_slice(&[3, 4, 5]);
3920 stamp_elem_type(a as *mut u8, ELEM_TYPE_I64);
3921 stamp_elem_type(b as *mut u8, ELEM_TYPE_I64);
3922 let view_a = as_v2_typed_array(a as u64, NativeKind::Ptr(HeapKind::TypedArray))
3923 .unwrap();
3924 let view_b = as_v2_typed_array(b as u64, NativeKind::Ptr(HeapKind::TypedArray))
3925 .unwrap();
3926 let new_ptr = concat_arrays(&view_a, &view_b).unwrap();
3927 let new_view =
3928 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3929 .unwrap();
3930 assert_eq!(new_view.elem_type, V2ElemType::I64);
3931 assert_eq!(new_view.len, 5);
3932 let new_arr = new_ptr as *const TypedArray<i64>;
3933 let data = (*new_arr).data;
3934 assert_eq!(*data.add(0), 1);
3935 assert_eq!(*data.add(1), 2);
3936 assert_eq!(*data.add(2), 3);
3937 assert_eq!(*data.add(3), 4);
3938 assert_eq!(*data.add(4), 5);
3939 TypedArray::<i64>::drop_array(a);
3940 TypedArray::<i64>::drop_array(b);
3941 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
3942 }
3943 }
3944
3945 #[test]
3946 fn test_concat_arrays_kind_mismatch() {
3947 unsafe {
3948 let a = TypedArray::<i64>::from_slice(&[1, 2]);
3949 let b = TypedArray::<f64>::from_slice(&[3.0, 4.0]);
3950 stamp_elem_type(a as *mut u8, ELEM_TYPE_I64);
3951 stamp_elem_type(b as *mut u8, ELEM_TYPE_F64);
3952 let view_a = as_v2_typed_array(a as u64, NativeKind::Ptr(HeapKind::TypedArray))
3953 .unwrap();
3954 let view_b = as_v2_typed_array(b as u64, NativeKind::Ptr(HeapKind::TypedArray))
3955 .unwrap();
3956 assert!(concat_arrays(&view_a, &view_b).is_err());
3957 TypedArray::<i64>::drop_array(a);
3958 TypedArray::<f64>::drop_array(b);
3959 }
3960 }
3961
3962 #[test]
3963 fn test_slice_array_i64() {
3964 unsafe {
3965 let arr = TypedArray::<i64>::from_slice(&[10, 20, 30, 40, 50]);
3966 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3967 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3968 .unwrap();
3969 let new_ptr = slice_array(&view, 1, 4);
3970 let new_view =
3971 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3972 .unwrap();
3973 assert_eq!(new_view.elem_type, V2ElemType::I64);
3974 assert_eq!(new_view.len, 3);
3975 let new_arr = new_ptr as *const TypedArray<i64>;
3976 let data = (*new_arr).data;
3977 assert_eq!(*data.add(0), 20);
3978 assert_eq!(*data.add(1), 30);
3979 assert_eq!(*data.add(2), 40);
3980 TypedArray::<i64>::drop_array(arr);
3981 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
3982 }
3983 }
3984
3985 #[test]
3986 fn test_slice_array_clamps_oversize_end() {
3987 unsafe {
3988 let arr = TypedArray::<i64>::from_slice(&[10, 20, 30]);
3989 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
3990 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3991 .unwrap();
3992 let new_ptr = slice_array(&view, 2, 100);
3994 let new_view =
3995 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
3996 .unwrap();
3997 assert_eq!(new_view.len, 1);
3998 let new_arr = new_ptr as *const TypedArray<i64>;
3999 assert_eq!(*(*new_arr).data.add(0), 30);
4000 TypedArray::<i64>::drop_array(arr);
4001 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4002 }
4003 }
4004
4005 #[test]
4006 fn test_slice_array_inverted_range_empty() {
4007 unsafe {
4008 let arr = TypedArray::<i64>::from_slice(&[1, 2, 3]);
4009 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4010 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4011 .unwrap();
4012 let new_ptr = slice_array(&view, 5, 2);
4014 let new_view =
4015 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4016 .unwrap();
4017 assert_eq!(new_view.len, 0);
4018 TypedArray::<i64>::drop_array(arr);
4019 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4020 }
4021 }
4022
4023 #[test]
4024 fn test_take_array_i64() {
4025 unsafe {
4026 let arr = TypedArray::<i64>::from_slice(&[1, 2, 3, 4, 5]);
4027 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4028 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4029 .unwrap();
4030 let new_ptr = take_array(&view, 2);
4031 let new_view =
4032 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4033 .unwrap();
4034 assert_eq!(new_view.len, 2);
4035 let new_arr = new_ptr as *const TypedArray<i64>;
4036 assert_eq!(*(*new_arr).data.add(0), 1);
4037 assert_eq!(*(*new_arr).data.add(1), 2);
4038 TypedArray::<i64>::drop_array(arr);
4039 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4040 }
4041 }
4042
4043 #[test]
4044 fn test_take_array_n_exceeds_len() {
4045 unsafe {
4046 let arr = TypedArray::<i64>::from_slice(&[1, 2]);
4047 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4048 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4049 .unwrap();
4050 let new_ptr = take_array(&view, 100);
4052 let new_view =
4053 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4054 .unwrap();
4055 assert_eq!(new_view.len, 2);
4056 TypedArray::<i64>::drop_array(arr);
4057 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4058 }
4059 }
4060
4061 #[test]
4062 fn test_drop_array_n_i64() {
4063 unsafe {
4064 let arr = TypedArray::<i64>::from_slice(&[1, 2, 3, 4, 5]);
4065 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4066 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4067 .unwrap();
4068 let new_ptr = drop_array_n(&view, 2);
4069 let new_view =
4070 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4071 .unwrap();
4072 assert_eq!(new_view.len, 3);
4073 let new_arr = new_ptr as *const TypedArray<i64>;
4074 assert_eq!(*(*new_arr).data.add(0), 3);
4075 assert_eq!(*(*new_arr).data.add(1), 4);
4076 assert_eq!(*(*new_arr).data.add(2), 5);
4077 TypedArray::<i64>::drop_array(arr);
4078 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4079 }
4080 }
4081
4082 #[test]
4083 fn test_drop_array_n_exceeds_len_yields_empty() {
4084 unsafe {
4085 let arr = TypedArray::<i64>::from_slice(&[1, 2]);
4086 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4087 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4088 .unwrap();
4089 let new_ptr = drop_array_n(&view, 100);
4090 let new_view =
4091 as_v2_typed_array(new_ptr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4092 .unwrap();
4093 assert_eq!(new_view.len, 0);
4094 TypedArray::<i64>::drop_array(arr);
4095 TypedArray::<i64>::drop_array(new_ptr as *mut TypedArray<i64>);
4096 }
4097 }
4098
4099 #[test]
4111 fn test_eq_element_scalar_i64() {
4112 assert!(eq_element(42, 42, V2ElemType::I64));
4113 assert!(!eq_element(42, 43, V2ElemType::I64));
4114 assert!(eq_element((-5i64) as u64, (-5i64) as u64, V2ElemType::I64));
4116 assert!(!eq_element((-5i64) as u64, (5i64) as u64, V2ElemType::I64));
4117 }
4118
4119 #[test]
4120 fn test_eq_element_scalar_f64_bitwise() {
4121 assert!(eq_element(1.5f64.to_bits(), 1.5f64.to_bits(), V2ElemType::F64));
4122 assert!(!eq_element(1.5f64.to_bits(), 2.5f64.to_bits(), V2ElemType::F64));
4123 let nan = f64::NAN.to_bits();
4127 assert!(eq_element(nan, nan, V2ElemType::F64));
4128 }
4129
4130 #[test]
4131 fn test_eq_element_scalar_bool() {
4132 assert!(eq_element(1, 1, V2ElemType::Bool));
4133 assert!(eq_element(0, 0, V2ElemType::Bool));
4134 assert!(!eq_element(1, 0, V2ElemType::Bool));
4135 }
4136
4137 #[test]
4138 fn test_eq_element_string_content() {
4139 unsafe {
4140 let s1 = StringObj::new("hello");
4141 let s2 = StringObj::new("hello"); let s3 = StringObj::new("world");
4143 assert!(eq_element(s1 as u64, s2 as u64, V2ElemType::String));
4144 assert!(!eq_element(s1 as u64, s3 as u64, V2ElemType::String));
4145 assert!(eq_element(0, 0, V2ElemType::String));
4147 assert!(!eq_element(s1 as u64, 0, V2ElemType::String));
4148 assert!(eq_element(s1 as u64, s1 as u64, V2ElemType::String));
4150 StringObj::drop(s1);
4151 StringObj::drop(s2);
4152 StringObj::drop(s3);
4153 }
4154 }
4155
4156 #[test]
4157 fn test_eq_element_decimal_content() {
4158 use rust_decimal::Decimal;
4159 use rust_decimal::prelude::FromPrimitive;
4160 unsafe {
4161 let d1 = DecimalObj::new(Decimal::from_f64(3.14).unwrap());
4162 let d2 = DecimalObj::new(Decimal::from_f64(3.14).unwrap());
4163 let d3 = DecimalObj::new(Decimal::from_f64(2.71).unwrap());
4164 assert!(eq_element(d1 as u64, d2 as u64, V2ElemType::Decimal));
4165 assert!(!eq_element(d1 as u64, d3 as u64, V2ElemType::Decimal));
4166 DecimalObj::drop(d1);
4167 DecimalObj::drop(d2);
4168 DecimalObj::drop(d3);
4169 }
4170 }
4171
4172 #[test]
4173 fn test_position_of_i64() {
4174 unsafe {
4175 let arr = TypedArray::<i64>::from_slice(&[10, 20, 30, 20, 40]);
4176 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4177 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4178 .unwrap();
4179 assert_eq!(position_of(&view, 10u64), Some(0));
4180 assert_eq!(position_of(&view, 20u64), Some(1)); assert_eq!(position_of(&view, 30u64), Some(2));
4182 assert_eq!(position_of(&view, 99u64), None);
4183 TypedArray::<i64>::drop_array(arr);
4184 }
4185 }
4186
4187 #[test]
4188 fn test_position_of_empty_returns_none() {
4189 unsafe {
4190 let arr = TypedArray::<i64>::with_capacity(0);
4191 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4192 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4193 .unwrap();
4194 assert_eq!(position_of(&view, 0u64), None);
4195 TypedArray::<i64>::drop_array(arr);
4196 }
4197 }
4198
4199 #[test]
4200 fn test_contains_element_i64() {
4201 unsafe {
4202 let arr = TypedArray::<i64>::from_slice(&[1, 2, 3, 4, 5]);
4203 stamp_elem_type(arr as *mut u8, ELEM_TYPE_I64);
4204 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4205 .unwrap();
4206 assert!(contains_element(&view, 3u64));
4207 assert!(!contains_element(&view, 99u64));
4208 TypedArray::<i64>::drop_array(arr);
4209 }
4210 }
4211
4212 #[test]
4213 fn test_position_of_f64_nan_bitwise() {
4214 unsafe {
4215 let arr = TypedArray::<f64>::from_slice(&[1.0, f64::NAN, 2.0]);
4216 stamp_elem_type(arr as *mut u8, ELEM_TYPE_F64);
4217 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4218 .unwrap();
4219 assert_eq!(position_of(&view, f64::NAN.to_bits()), Some(1));
4221 assert_eq!(position_of(&view, (1.0f64).to_bits()), Some(0));
4222 assert_eq!(position_of(&view, (99.0f64).to_bits()), None);
4223 TypedArray::<f64>::drop_array(arr);
4224 }
4225 }
4226
4227 #[test]
4228 fn test_position_of_string_content() {
4229 unsafe {
4230 let s1 = StringObj::new("a");
4231 let s2 = StringObj::new("b");
4232 let s3 = StringObj::new("c");
4233 let arr = TypedArray::<*const StringObj>::with_capacity(3);
4234 TypedArray::push(arr, s1 as *const StringObj);
4235 TypedArray::push(arr, s2 as *const StringObj);
4236 TypedArray::push(arr, s3 as *const StringObj);
4237 stamp_elem_type(arr as *mut u8, ELEM_TYPE_STRING);
4238 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4239 .unwrap();
4240 let needle = StringObj::new("b");
4244 assert_eq!(position_of(&view, needle as u64), Some(1));
4245 let other = StringObj::new("zzz");
4247 assert_eq!(position_of(&view, other as u64), None);
4248 assert!(contains_element(&view, needle as u64));
4249 assert!(!contains_element(&view, other as u64));
4250 TypedArray::<*const StringObj>::drop_array_heap(arr);
4251 StringObj::drop(needle);
4252 StringObj::drop(other);
4253 }
4254 }
4255
4256 #[test]
4257 fn test_position_of_decimal_content() {
4258 use rust_decimal::Decimal;
4259 use rust_decimal::prelude::FromPrimitive;
4260 unsafe {
4261 let d1 = DecimalObj::new(Decimal::from_f64(1.5).unwrap());
4262 let d2 = DecimalObj::new(Decimal::from_f64(2.5).unwrap());
4263 let arr = TypedArray::<*const DecimalObj>::with_capacity(2);
4264 TypedArray::push(arr, d1 as *const DecimalObj);
4265 TypedArray::push(arr, d2 as *const DecimalObj);
4266 stamp_elem_type(arr as *mut u8, ELEM_TYPE_DECIMAL);
4267 let view = as_v2_typed_array(arr as u64, NativeKind::Ptr(HeapKind::TypedArray))
4268 .unwrap();
4269 let needle = DecimalObj::new(Decimal::from_f64(2.5).unwrap());
4270 assert_eq!(position_of(&view, needle as u64), Some(1));
4271 let other = DecimalObj::new(Decimal::from_f64(9.9).unwrap());
4272 assert_eq!(position_of(&view, other as u64), None);
4273 TypedArray::<*const DecimalObj>::drop_array_heap(arr);
4274 DecimalObj::drop(needle);
4275 DecimalObj::drop(other);
4276 }
4277 }
4278
4279 #[test]
4280 fn test_position_of_typed_object_schema_mismatch() {
4281 use shape_value::slot::ValueSlot;
4282 use std::sync::Arc;
4283 unsafe {
4284 let kinds_a: Arc<[NativeKind]> = Arc::from(vec![].into_boxed_slice());
4287 let kinds_b: Arc<[NativeKind]> = Arc::from(vec![].into_boxed_slice());
4288 let obj_a = TypedObjectStorage::_new(
4289 1,
4290 vec![].into_boxed_slice() as Box<[ValueSlot]>,
4291 0,
4292 kinds_a,
4293 );
4294 let obj_b = TypedObjectStorage::_new(
4295 2,
4296 vec![].into_boxed_slice() as Box<[ValueSlot]>,
4297 0,
4298 kinds_b,
4299 );
4300 assert!(!eq_element(
4301 obj_a as u64,
4302 obj_b as u64,
4303 V2ElemType::TypedObject
4304 ));
4305 TypedObjectStorage::_drop(obj_a);
4306 TypedObjectStorage::_drop(obj_b);
4307 }
4308 }
4309
4310 #[test]
4311 fn test_position_of_typed_object_same_schema_equal_fields() {
4312 use shape_value::slot::ValueSlot;
4313 use std::sync::Arc;
4314 unsafe {
4315 let kinds: Arc<[NativeKind]> = Arc::from(vec![NativeKind::Int64].into_boxed_slice());
4318 let obj_a = TypedObjectStorage::_new(
4319 7,
4320 vec![ValueSlot::from_raw(42u64)].into_boxed_slice(),
4321 0,
4322 kinds.clone(),
4323 );
4324 let obj_b = TypedObjectStorage::_new(
4325 7,
4326 vec![ValueSlot::from_raw(42u64)].into_boxed_slice(),
4327 0,
4328 kinds.clone(),
4329 );
4330 let obj_c = TypedObjectStorage::_new(
4331 7,
4332 vec![ValueSlot::from_raw(99u64)].into_boxed_slice(),
4333 0,
4334 kinds.clone(),
4335 );
4336 assert!(eq_element(
4337 obj_a as u64,
4338 obj_b as u64,
4339 V2ElemType::TypedObject
4340 ));
4341 assert!(!eq_element(
4342 obj_a as u64,
4343 obj_c as u64,
4344 V2ElemType::TypedObject
4345 ));
4346 assert!(eq_element(
4348 obj_a as u64,
4349 obj_a as u64,
4350 V2ElemType::TypedObject
4351 ));
4352 assert!(!eq_element(0, obj_a as u64, V2ElemType::TypedObject));
4354 assert!(eq_element(0, 0, V2ElemType::TypedObject));
4355 TypedObjectStorage::_drop(obj_a);
4356 TypedObjectStorage::_drop(obj_b);
4357 TypedObjectStorage::_drop(obj_c);
4358 }
4359 }
4360}