Skip to main content

parquet_variant_compute/
cast_to_variant.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::arrow_to_variant::make_arrow_to_variant_row_builder;
6use crate::{VariantArray, VariantArrayBuilder};
7use arrow::array::Array;
8use arrow::compute::CastOptions;
9use arrow_schema::ArrowError;
10
11/// Casts a typed arrow [`Array`] to a [`VariantArray`]. This is useful when you
12/// need to convert a specific data type
13///
14/// # Arguments
15/// * `input` - A reference to the input [`Array`] to cast
16///
17/// # Notes
18/// If the input array element is null, the corresponding element in the
19/// output `VariantArray` will also be null (not `Variant::Null`).
20///
21/// # Example
22/// ```
23/// # use arrow::array::{Array, ArrayRef, Int64Array};
24/// # use parquet_variant::Variant;
25/// # use parquet_variant_compute::cast_to_variant;
26/// // input is an Int64Array, which will be cast to a VariantArray
27/// let input = Int64Array::from(vec![Some(1), None, Some(3)]);
28/// let result = cast_to_variant(&input).unwrap();
29/// assert_eq!(result.len(), 3);
30/// assert_eq!(result.value(0), Variant::Int64(1));
31/// assert!(result.is_null(1)); // note null, not Variant::Null
32/// assert_eq!(result.value(2), Variant::Int64(3));
33/// ```
34///
35/// For `DataType::Timestamp`s: if the timestamp has any level of precision
36/// greater than a microsecond, it will be truncated. For example
37/// `1970-01-01T00:00:01.234567890Z`
38/// will be truncated to
39/// `1970-01-01T00:00:01.234567Z`
40///
41/// # Arguments
42/// * `input` - The array to convert to VariantArray
43/// * `options` - Options controlling conversion behavior
44pub fn cast_to_variant_with_options(
45    input: &dyn Array,
46    options: &CastOptions,
47) -> Result<VariantArray, ArrowError> {
48    // Fast path: any all-null input maps to an all-null VariantArray.
49    if input.null_count() == input.len() {
50        let mut array_builder = VariantArrayBuilder::new(input.len());
51        array_builder.append_nulls(input.len());
52        return Ok(array_builder.build());
53    }
54
55    // Create row builder for the input array type
56    let mut row_builder = make_arrow_to_variant_row_builder(input.data_type(), input, options)?;
57
58    // Create output array builder
59    let mut array_builder = VariantArrayBuilder::new(input.len());
60
61    // Process each row using the row builder
62    for i in 0..input.len() {
63        row_builder.append_row(&mut array_builder, i)?;
64    }
65
66    Ok(array_builder.build())
67}
68
69/// Convert an array to a [`VariantArray`] with strict mode enabled (returns errors on conversion
70/// failures).
71///
72/// This function provides backward compatibility. For non-strict behavior,
73/// use [`cast_to_variant_with_options`] with `CastOptions { safe: true, ..Default::default() }`.
74pub fn cast_to_variant(input: &dyn Array) -> Result<VariantArray, ArrowError> {
75    cast_to_variant_with_options(
76        input,
77        &CastOptions {
78            safe: false,
79            ..Default::default()
80        },
81    )
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87    use arrow::array::{
88        ArrayRef, BinaryArray, BooleanArray, Date32Array, Date64Array, Decimal32Array,
89        Decimal64Array, Decimal128Array, Decimal256Array, DictionaryArray,
90        DurationMicrosecondArray, DurationMillisecondArray, DurationNanosecondArray,
91        DurationSecondArray, FixedSizeBinaryBuilder, FixedSizeListBuilder, Float16Array,
92        Float32Array, Float64Array, GenericByteBuilder, GenericByteViewBuilder, Int8Array,
93        Int16Array, Int32Array, Int64Array, IntervalDayTimeArray, IntervalMonthDayNanoArray,
94        IntervalYearMonthArray, LargeListArray, LargeListViewBuilder, LargeStringArray, ListArray,
95        ListViewBuilder, MapArray, NullArray, StringArray, StringRunBuilder, StringViewArray,
96        StructArray, Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray,
97        Time64NanosecondArray, TimestampMicrosecondArray, TimestampMillisecondArray,
98        TimestampNanosecondArray, TimestampSecondArray, UInt8Array, UInt16Array, UInt32Array,
99        UInt64Array, UnionArray,
100    };
101    use arrow::buffer::{NullBuffer, OffsetBuffer, ScalarBuffer};
102    use arrow::datatypes::{
103        BinaryType, BinaryViewType, Date32Type, Date64Type, Int8Type, Int32Type, Int64Type,
104        IntervalDayTime, IntervalMonthDayNano, LargeBinaryType, i256,
105    };
106    use arrow::temporal_conversions::timestamp_s_to_datetime;
107    use arrow_schema::{
108        DECIMAL32_MAX_PRECISION, DECIMAL64_MAX_PRECISION, DECIMAL128_MAX_PRECISION,
109    };
110    use arrow_schema::{DataType, Field, Fields, UnionFields};
111    use chrono::{DateTime, NaiveDate, NaiveTime};
112    use half::f16;
113    use parquet_variant::{
114        Variant, VariantBuilder, VariantBuilderExt, VariantDecimal4, VariantDecimal8,
115        VariantDecimal16,
116    };
117    use std::{sync::Arc, vec};
118
119    macro_rules! max_unscaled_value {
120        (32, $precision:expr) => {
121            (u32::pow(10, $precision as u32) - 1) as i32
122        };
123        (64, $precision:expr) => {
124            (u64::pow(10, $precision as u32) - 1) as i64
125        };
126        (128, $precision:expr) => {
127            (u128::pow(10, $precision as u32) - 1) as i128
128        };
129    }
130
131    #[test]
132    fn test_cast_to_variant_null() {
133        run_test(Arc::new(NullArray::new(2)), vec![None, None])
134    }
135
136    #[test]
137    fn test_cast_to_variant_bool() {
138        run_test(
139            Arc::new(BooleanArray::from(vec![Some(true), None, Some(false)])),
140            vec![
141                Some(Variant::BooleanTrue),
142                None,
143                Some(Variant::BooleanFalse),
144            ],
145        );
146    }
147
148    #[test]
149    fn test_cast_to_variant_int8() {
150        run_test(
151            Arc::new(Int8Array::from(vec![
152                Some(i8::MIN),
153                None,
154                Some(-1),
155                Some(1),
156                Some(i8::MAX),
157            ])),
158            vec![
159                Some(Variant::Int8(i8::MIN)),
160                None,
161                Some(Variant::Int8(-1)),
162                Some(Variant::Int8(1)),
163                Some(Variant::Int8(i8::MAX)),
164            ],
165        )
166    }
167
168    #[test]
169    fn test_cast_to_variant_int16() {
170        run_test(
171            Arc::new(Int16Array::from(vec![
172                Some(i16::MIN),
173                None,
174                Some(-1),
175                Some(1),
176                Some(i16::MAX),
177            ])),
178            vec![
179                Some(Variant::Int16(i16::MIN)),
180                None,
181                Some(Variant::Int16(-1)),
182                Some(Variant::Int16(1)),
183                Some(Variant::Int16(i16::MAX)),
184            ],
185        )
186    }
187
188    #[test]
189    fn test_cast_to_variant_int32() {
190        run_test(
191            Arc::new(Int32Array::from(vec![
192                Some(i32::MIN),
193                None,
194                Some(-1),
195                Some(1),
196                Some(i32::MAX),
197            ])),
198            vec![
199                Some(Variant::Int32(i32::MIN)),
200                None,
201                Some(Variant::Int32(-1)),
202                Some(Variant::Int32(1)),
203                Some(Variant::Int32(i32::MAX)),
204            ],
205        )
206    }
207
208    #[test]
209    fn test_cast_to_variant_int64() {
210        run_test(
211            Arc::new(Int64Array::from(vec![
212                Some(i64::MIN),
213                None,
214                Some(-1),
215                Some(1),
216                Some(i64::MAX),
217            ])),
218            vec![
219                Some(Variant::Int64(i64::MIN)),
220                None,
221                Some(Variant::Int64(-1)),
222                Some(Variant::Int64(1)),
223                Some(Variant::Int64(i64::MAX)),
224            ],
225        )
226    }
227
228    #[test]
229    fn test_cast_to_variant_uint8() {
230        run_test(
231            Arc::new(UInt8Array::from(vec![
232                Some(0),
233                None,
234                Some(1),
235                Some(127),
236                Some(u8::MAX),
237            ])),
238            vec![
239                Some(Variant::Int8(0)),
240                None,
241                Some(Variant::Int8(1)),
242                Some(Variant::Int8(127)),
243                Some(Variant::Int16(255)), // u8::MAX cannot fit in Int8
244            ],
245        )
246    }
247
248    #[test]
249    fn test_cast_to_variant_uint16() {
250        run_test(
251            Arc::new(UInt16Array::from(vec![
252                Some(0),
253                None,
254                Some(1),
255                Some(32767),
256                Some(u16::MAX),
257            ])),
258            vec![
259                Some(Variant::Int16(0)),
260                None,
261                Some(Variant::Int16(1)),
262                Some(Variant::Int16(32767)),
263                Some(Variant::Int32(65535)), // u16::MAX cannot fit in Int16
264            ],
265        )
266    }
267
268    #[test]
269    fn test_cast_to_variant_uint32() {
270        run_test(
271            Arc::new(UInt32Array::from(vec![
272                Some(0),
273                None,
274                Some(1),
275                Some(2147483647),
276                Some(u32::MAX),
277            ])),
278            vec![
279                Some(Variant::Int32(0)),
280                None,
281                Some(Variant::Int32(1)),
282                Some(Variant::Int32(2147483647)),
283                Some(Variant::Int64(4294967295)), // u32::MAX cannot fit in Int32
284            ],
285        )
286    }
287
288    #[test]
289    fn test_cast_to_variant_uint64() {
290        run_test(
291            Arc::new(UInt64Array::from(vec![
292                Some(0),
293                None,
294                Some(1),
295                Some(9223372036854775807),
296                Some(u64::MAX),
297            ])),
298            vec![
299                Some(Variant::Int64(0)),
300                None,
301                Some(Variant::Int64(1)),
302                Some(Variant::Int64(9223372036854775807)),
303                Some(Variant::Decimal16(
304                    // u64::MAX cannot fit in Int64
305                    VariantDecimal16::try_from(18446744073709551615).unwrap(),
306                )),
307            ],
308        )
309    }
310
311    #[test]
312    fn test_cast_to_variant_float16() {
313        run_test(
314            Arc::new(Float16Array::from(vec![
315                Some(f16::MIN),
316                None,
317                Some(f16::from_f32(-1.5)),
318                Some(f16::from_f32(0.0)),
319                Some(f16::from_f32(1.5)),
320                Some(f16::MAX),
321            ])),
322            vec![
323                Some(Variant::Float(f16::MIN.into())),
324                None,
325                Some(Variant::Float(-1.5)),
326                Some(Variant::Float(0.0)),
327                Some(Variant::Float(1.5)),
328                Some(Variant::Float(f16::MAX.into())),
329            ],
330        )
331    }
332
333    #[test]
334    fn test_cast_to_variant_float32() {
335        run_test(
336            Arc::new(Float32Array::from(vec![
337                Some(f32::MIN),
338                None,
339                Some(-1.5),
340                Some(0.0),
341                Some(1.5),
342                Some(f32::MAX),
343            ])),
344            vec![
345                Some(Variant::Float(f32::MIN)),
346                None,
347                Some(Variant::Float(-1.5)),
348                Some(Variant::Float(0.0)),
349                Some(Variant::Float(1.5)),
350                Some(Variant::Float(f32::MAX)),
351            ],
352        )
353    }
354
355    #[test]
356    fn test_cast_to_variant_float64() {
357        run_test(
358            Arc::new(Float64Array::from(vec![
359                Some(f64::MIN),
360                None,
361                Some(-1.5),
362                Some(0.0),
363                Some(1.5),
364                Some(f64::MAX),
365            ])),
366            vec![
367                Some(Variant::Double(f64::MIN)),
368                None,
369                Some(Variant::Double(-1.5)),
370                Some(Variant::Double(0.0)),
371                Some(Variant::Double(1.5)),
372                Some(Variant::Double(f64::MAX)),
373            ],
374        )
375    }
376
377    #[test]
378    fn test_cast_to_variant_decimal32() {
379        run_test(
380            Arc::new(
381                Decimal32Array::from(vec![
382                    Some(i32::MIN),
383                    Some(-max_unscaled_value!(32, DECIMAL32_MAX_PRECISION) - 1), // Overflow value will be cast to Null
384                    Some(-max_unscaled_value!(32, DECIMAL32_MAX_PRECISION)), // The min of Decimal32 with positive scale that can be cast to VariantDecimal4
385                    None,
386                    Some(-123),
387                    Some(0),
388                    Some(123),
389                    Some(max_unscaled_value!(32, DECIMAL32_MAX_PRECISION)), // The max of Decimal32 with positive scale that can be cast to VariantDecimal4
390                    Some(max_unscaled_value!(32, DECIMAL32_MAX_PRECISION) + 1), // Overflow value will be cast to Null
391                    Some(i32::MAX),
392                ])
393                .with_precision_and_scale(DECIMAL32_MAX_PRECISION, 3)
394                .unwrap(),
395            ),
396            vec![
397                Some(Variant::Null),
398                Some(Variant::Null),
399                Some(
400                    VariantDecimal4::try_new(-max_unscaled_value!(32, DECIMAL32_MAX_PRECISION), 3)
401                        .unwrap()
402                        .into(),
403                ),
404                None,
405                Some(VariantDecimal4::try_new(-123, 3).unwrap().into()),
406                Some(VariantDecimal4::try_new(0, 3).unwrap().into()),
407                Some(VariantDecimal4::try_new(123, 3).unwrap().into()),
408                Some(
409                    VariantDecimal4::try_new(max_unscaled_value!(32, DECIMAL32_MAX_PRECISION), 3)
410                        .unwrap()
411                        .into(),
412                ),
413                Some(Variant::Null),
414                Some(Variant::Null),
415            ],
416        )
417    }
418
419    #[test]
420    fn test_cast_to_variant_decimal32_negative_scale() {
421        run_test(
422            Arc::new(
423                Decimal32Array::from(vec![
424                    Some(i32::MIN),
425                    Some(-max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3) - 1), // Overflow value will be cast to Null
426                    Some(-max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3)), // The min of Decimal32 with scale -3 that can be cast to VariantDecimal4
427                    None,
428                    Some(-123),
429                    Some(0),
430                    Some(123),
431                    Some(max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3)), // The max of Decimal32 with scale -3 that can be cast to VariantDecimal4
432                    Some(max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3) + 1), // Overflow value will be cast to Null
433                    Some(i32::MAX),
434                ])
435                .with_precision_and_scale(DECIMAL32_MAX_PRECISION, -3)
436                .unwrap(),
437            ),
438            vec![
439                Some(Variant::Null),
440                Some(Variant::Null),
441                Some(
442                    VariantDecimal4::try_new(
443                        -max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3) * 1000,
444                        0,
445                    )
446                    .unwrap()
447                    .into(),
448                ),
449                None,
450                Some(VariantDecimal4::try_new(-123_000, 0).unwrap().into()),
451                Some(VariantDecimal4::try_new(0, 0).unwrap().into()),
452                Some(VariantDecimal4::try_new(123_000, 0).unwrap().into()),
453                Some(
454                    VariantDecimal4::try_new(
455                        max_unscaled_value!(32, DECIMAL32_MAX_PRECISION - 3) * 1000,
456                        0,
457                    )
458                    .unwrap()
459                    .into(),
460                ),
461                Some(Variant::Null),
462                Some(Variant::Null),
463            ],
464        )
465    }
466
467    #[test]
468    fn test_cast_to_variant_decimal32_overflow_strict_mode() {
469        run_test_in_strict_mode(
470            Arc::new(
471                Decimal32Array::from(vec![Some(i32::MIN)])
472                    .with_precision_and_scale(DECIMAL32_MAX_PRECISION, 3)
473                    .unwrap(),
474            ),
475            Err(ArrowError::ComputeError(
476                "Failed to convert value at index 0: conversion failed".to_string(),
477            )),
478        );
479    }
480
481    #[test]
482    fn test_cast_to_variant_decimal64() {
483        run_test(
484            Arc::new(
485                Decimal64Array::from(vec![
486                    Some(i64::MIN),
487                    Some(-max_unscaled_value!(64, DECIMAL64_MAX_PRECISION) - 1), // Overflow value will be cast to Null
488                    Some(-max_unscaled_value!(64, DECIMAL64_MAX_PRECISION)), // The min of Decimal64 with positive scale that can be cast to VariantDecimal8
489                    None,
490                    Some(-123),
491                    Some(0),
492                    Some(123),
493                    Some(max_unscaled_value!(64, DECIMAL64_MAX_PRECISION)), // The max of Decimal64 with positive scale that can be cast to VariantDecimal8
494                    Some(max_unscaled_value!(64, DECIMAL64_MAX_PRECISION) + 1), // Overflow value will be cast to Null
495                    Some(i64::MAX),
496                ])
497                .with_precision_and_scale(DECIMAL64_MAX_PRECISION, 3)
498                .unwrap(),
499            ),
500            vec![
501                Some(Variant::Null),
502                Some(Variant::Null),
503                Some(
504                    VariantDecimal8::try_new(-max_unscaled_value!(64, DECIMAL64_MAX_PRECISION), 3)
505                        .unwrap()
506                        .into(),
507                ),
508                None,
509                Some(VariantDecimal8::try_new(-123, 3).unwrap().into()),
510                Some(VariantDecimal8::try_new(0, 3).unwrap().into()),
511                Some(VariantDecimal8::try_new(123, 3).unwrap().into()),
512                Some(
513                    VariantDecimal8::try_new(max_unscaled_value!(64, DECIMAL64_MAX_PRECISION), 3)
514                        .unwrap()
515                        .into(),
516                ),
517                Some(Variant::Null),
518                Some(Variant::Null),
519            ],
520        )
521    }
522
523    #[test]
524    fn test_cast_to_variant_decimal64_negative_scale() {
525        run_test(
526            Arc::new(
527                Decimal64Array::from(vec![
528                    Some(i64::MIN),
529                    Some(-max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3) - 1), // Overflow value will be cast to Null
530                    Some(-max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3)), // The min of Decimal64 with scale -3 that can be cast to VariantDecimal8
531                    None,
532                    Some(-123),
533                    Some(0),
534                    Some(123),
535                    Some(max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3)), // The max of Decimal64 with scale -3 that can be cast to VariantDecimal8
536                    Some(max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3) + 1), // Overflow value will be cast to Null
537                    Some(i64::MAX),
538                ])
539                .with_precision_and_scale(DECIMAL64_MAX_PRECISION, -3)
540                .unwrap(),
541            ),
542            vec![
543                Some(Variant::Null),
544                Some(Variant::Null),
545                Some(
546                    VariantDecimal8::try_new(
547                        -max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3) * 1000,
548                        0,
549                    )
550                    .unwrap()
551                    .into(),
552                ),
553                None,
554                Some(VariantDecimal8::try_new(-123_000, 0).unwrap().into()),
555                Some(VariantDecimal8::try_new(0, 0).unwrap().into()),
556                Some(VariantDecimal8::try_new(123_000, 0).unwrap().into()),
557                Some(
558                    VariantDecimal8::try_new(
559                        max_unscaled_value!(64, DECIMAL64_MAX_PRECISION - 3) * 1000,
560                        0,
561                    )
562                    .unwrap()
563                    .into(),
564                ),
565                Some(Variant::Null),
566                Some(Variant::Null),
567            ],
568        )
569    }
570
571    #[test]
572    fn test_cast_to_variant_decimal64_overflow_strict_mode() {
573        run_test_in_strict_mode(
574            Arc::new(
575                Decimal64Array::from(vec![Some(i64::MAX)])
576                    .with_precision_and_scale(DECIMAL64_MAX_PRECISION, 3)
577                    .unwrap(),
578            ),
579            Err(ArrowError::ComputeError(
580                "Failed to convert value at index 0: conversion failed".to_string(),
581            )),
582        );
583    }
584
585    #[test]
586    fn test_cast_to_variant_decimal128() {
587        run_test(
588            Arc::new(
589                Decimal128Array::from(vec![
590                    Some(i128::MIN),
591                    Some(-max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) - 1), // Overflow value will be cast to Null
592                    Some(-max_unscaled_value!(128, DECIMAL128_MAX_PRECISION)), // The min of Decimal128 with positive scale that can be cast to VariantDecimal16
593                    None,
594                    Some(-123),
595                    Some(0),
596                    Some(123),
597                    Some(max_unscaled_value!(128, DECIMAL128_MAX_PRECISION)), // The max of Decimal128 with positive scale that can be cast to VariantDecimal16
598                    Some(max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) + 1), // Overflow value will be cast to Null
599                    Some(i128::MAX),
600                ])
601                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, 3)
602                .unwrap(),
603            ),
604            vec![
605                Some(Variant::Null),
606                Some(Variant::Null),
607                Some(
608                    VariantDecimal16::try_new(
609                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION),
610                        3,
611                    )
612                    .unwrap()
613                    .into(),
614                ),
615                None,
616                Some(VariantDecimal16::try_new(-123, 3).unwrap().into()),
617                Some(VariantDecimal16::try_new(0, 3).unwrap().into()),
618                Some(VariantDecimal16::try_new(123, 3).unwrap().into()),
619                Some(
620                    VariantDecimal16::try_new(
621                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION),
622                        3,
623                    )
624                    .unwrap()
625                    .into(),
626                ),
627                Some(Variant::Null),
628                Some(Variant::Null),
629            ],
630        )
631    }
632
633    #[test]
634    fn test_cast_to_variant_decimal128_negative_scale() {
635        run_test(
636            Arc::new(
637                Decimal128Array::from(vec![
638                    Some(i128::MIN),
639                    Some(-max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) - 1), // Overflow value will be cast to Null
640                    Some(-max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3)), // The min of Decimal128 with scale -3 that can be cast to VariantDecimal16
641                    None,
642                    Some(-123),
643                    Some(0),
644                    Some(123),
645                    Some(max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3)), // The max of Decimal128 with scale -3 that can be cast to VariantDecimal16
646                    Some(max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) + 1), // Overflow value will be cast to Null
647                    Some(i128::MAX),
648                ])
649                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, -3)
650                .unwrap(),
651            ),
652            vec![
653                Some(Variant::Null),
654                Some(Variant::Null),
655                Some(
656                    VariantDecimal16::try_new(
657                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) * 1000,
658                        0,
659                    )
660                    .unwrap()
661                    .into(),
662                ),
663                None,
664                Some(VariantDecimal16::try_new(-123_000, 0).unwrap().into()),
665                Some(VariantDecimal16::try_new(0, 0).unwrap().into()),
666                Some(VariantDecimal16::try_new(123_000, 0).unwrap().into()),
667                Some(
668                    VariantDecimal16::try_new(
669                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) * 1000,
670                        0,
671                    )
672                    .unwrap()
673                    .into(),
674                ),
675                Some(Variant::Null),
676                Some(Variant::Null),
677            ],
678        )
679    }
680
681    #[test]
682    fn test_cast_to_variant_decimal128_overflow_strict_mode() {
683        run_test_in_strict_mode(
684            Arc::new(
685                Decimal128Array::from(vec![Some(
686                    -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) - 1,
687                )])
688                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, 3)
689                .unwrap(),
690            ),
691            Err(ArrowError::ComputeError(
692                "Failed to convert value at index 0: conversion failed".to_string(),
693            )),
694        );
695    }
696
697    #[test]
698    fn test_cast_to_variant_decimal256() {
699        run_test(
700            Arc::new(
701                Decimal256Array::from(vec![
702                    Some(i256::MIN),
703                    Some(i256::from_i128(
704                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) - 1,
705                    )), // Overflow value will be cast to Null
706                    Some(i256::from_i128(-max_unscaled_value!(
707                        128,
708                        DECIMAL128_MAX_PRECISION
709                    ))), // The min of Decimal256 with positive scale that can be cast to VariantDecimal16
710                    None,
711                    Some(i256::from_i128(-123)),
712                    Some(i256::from_i128(0)),
713                    Some(i256::from_i128(123)),
714                    Some(i256::from_i128(max_unscaled_value!(
715                        128,
716                        DECIMAL128_MAX_PRECISION
717                    ))), // The max of Decimal256 with positive scale that can be cast to VariantDecimal16
718                    Some(i256::from_i128(
719                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) + 1,
720                    )), // Overflow value will be cast to Null
721                    Some(i256::MAX),
722                ])
723                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, 3)
724                .unwrap(),
725            ),
726            vec![
727                Some(Variant::Null),
728                Some(Variant::Null),
729                Some(
730                    VariantDecimal16::try_new(
731                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION),
732                        3,
733                    )
734                    .unwrap()
735                    .into(),
736                ),
737                None,
738                Some(VariantDecimal16::try_new(-123, 3).unwrap().into()),
739                Some(VariantDecimal16::try_new(0, 3).unwrap().into()),
740                Some(VariantDecimal16::try_new(123, 3).unwrap().into()),
741                Some(
742                    VariantDecimal16::try_new(
743                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION),
744                        3,
745                    )
746                    .unwrap()
747                    .into(),
748                ),
749                Some(Variant::Null),
750                Some(Variant::Null),
751            ],
752        )
753    }
754
755    #[test]
756    fn test_cast_to_variant_decimal256_negative_scale() {
757        run_test(
758            Arc::new(
759                Decimal256Array::from(vec![
760                    Some(i256::MIN),
761                    Some(i256::from_i128(
762                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) - 1,
763                    )), // Overflow value will be cast to Null
764                    Some(i256::from_i128(-max_unscaled_value!(
765                        128,
766                        DECIMAL128_MAX_PRECISION - 3
767                    ))), // The min of Decimal256 with scale -3 that can be cast to VariantDecimal16
768                    None,
769                    Some(i256::from_i128(-123)),
770                    Some(i256::from_i128(0)),
771                    Some(i256::from_i128(123)),
772                    Some(i256::from_i128(max_unscaled_value!(
773                        128,
774                        DECIMAL128_MAX_PRECISION - 3
775                    ))), // The max of Decimal256 with scale -3 that can be cast to VariantDecimal16
776                    Some(i256::from_i128(
777                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) + 1,
778                    )), // Overflow value will be cast to Null
779                    Some(i256::MAX),
780                ])
781                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, -3)
782                .unwrap(),
783            ),
784            vec![
785                Some(Variant::Null),
786                Some(Variant::Null),
787                Some(
788                    VariantDecimal16::try_new(
789                        -max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) * 1000,
790                        0,
791                    )
792                    .unwrap()
793                    .into(),
794                ),
795                None,
796                Some(VariantDecimal16::try_new(-123_000, 0).unwrap().into()),
797                Some(VariantDecimal16::try_new(0, 0).unwrap().into()),
798                Some(VariantDecimal16::try_new(123_000, 0).unwrap().into()),
799                Some(
800                    VariantDecimal16::try_new(
801                        max_unscaled_value!(128, DECIMAL128_MAX_PRECISION - 3) * 1000,
802                        0,
803                    )
804                    .unwrap()
805                    .into(),
806                ),
807                Some(Variant::Null),
808                Some(Variant::Null),
809            ],
810        )
811    }
812
813    #[test]
814    fn test_cast_to_variant_decimal256_overflow_strict_mode() {
815        run_test_in_strict_mode(
816            Arc::new(
817                Decimal256Array::from(vec![Some(i256::from_i128(
818                    max_unscaled_value!(128, DECIMAL128_MAX_PRECISION) + 1,
819                ))])
820                .with_precision_and_scale(DECIMAL128_MAX_PRECISION, 3)
821                .unwrap(),
822            ),
823            Err(ArrowError::ComputeError(
824                "Failed to convert value at index 0: conversion failed".to_string(),
825            )),
826        );
827    }
828
829    #[test]
830    fn test_cast_to_variant_timestamp() {
831        let run_array_tests =
832            |microseconds: i64, array_ntz: Arc<dyn Array>, array_tz: Arc<dyn Array>| {
833                let timestamp = DateTime::from_timestamp_nanos(microseconds * 1000);
834                run_test(
835                    array_tz,
836                    vec![Some(Variant::TimestampMicros(timestamp)), None],
837                );
838                run_test(
839                    array_ntz,
840                    vec![
841                        Some(Variant::TimestampNtzMicros(timestamp.naive_utc())),
842                        None,
843                    ],
844                );
845            };
846
847        let nanosecond = 1234567890;
848        let microsecond = 1234567;
849        let millisecond = 1234;
850        let second = 1;
851
852        let second_array = TimestampSecondArray::from(vec![Some(second), None]);
853        run_array_tests(
854            second * 1000 * 1000,
855            Arc::new(second_array.clone()),
856            Arc::new(second_array.with_timezone("+01:00".to_string())),
857        );
858
859        let millisecond_array = TimestampMillisecondArray::from(vec![Some(millisecond), None]);
860        run_array_tests(
861            millisecond * 1000,
862            Arc::new(millisecond_array.clone()),
863            Arc::new(millisecond_array.with_timezone("+01:00".to_string())),
864        );
865
866        let microsecond_array = TimestampMicrosecondArray::from(vec![Some(microsecond), None]);
867        run_array_tests(
868            microsecond,
869            Arc::new(microsecond_array.clone()),
870            Arc::new(microsecond_array.with_timezone("+01:00".to_string())),
871        );
872
873        let timestamp = DateTime::from_timestamp_nanos(nanosecond);
874        let nanosecond_array = TimestampNanosecondArray::from(vec![Some(nanosecond), None]);
875        run_test(
876            Arc::new(nanosecond_array.clone()),
877            vec![
878                Some(Variant::TimestampNtzNanos(timestamp.naive_utc())),
879                None,
880            ],
881        );
882        run_test(
883            Arc::new(nanosecond_array.with_timezone("+01:00".to_string())),
884            vec![Some(Variant::TimestampNanos(timestamp)), None],
885        );
886    }
887
888    #[test]
889    fn test_cast_to_variant_timestamp_overflow_strict_mode() {
890        let ts_array = TimestampSecondArray::from(vec![Some(i64::MAX), Some(0), Some(1609459200)])
891            .with_timezone_opt(None::<&str>);
892
893        let values = Arc::new(ts_array);
894        run_test_in_strict_mode(
895            values,
896            Err(ArrowError::ComputeError(
897                "Failed to convert value at index 0: conversion failed".to_string(),
898            )),
899        );
900    }
901
902    #[test]
903    fn test_cast_to_variant_timestamp_overflow_non_strict_mode() {
904        let ts_array = TimestampSecondArray::from(vec![Some(i64::MAX), Some(0), Some(1609459200)])
905            .with_timezone_opt(None::<&str>);
906
907        let values = Arc::new(ts_array);
908        run_test(
909            values,
910            vec![
911                Some(Variant::Null), // Invalid timestamp becomes null
912                Some(Variant::TimestampNtzMicros(
913                    timestamp_s_to_datetime(0).unwrap(),
914                )),
915                Some(Variant::TimestampNtzMicros(
916                    timestamp_s_to_datetime(1609459200).unwrap(),
917                )),
918            ],
919        );
920    }
921
922    #[test]
923    fn test_cast_to_variant_date() {
924        // Date32Array
925        run_test(
926            Arc::new(Date32Array::from(vec![
927                Some(Date32Type::from_naive_date(NaiveDate::MIN)),
928                None,
929                Some(Date32Type::from_naive_date(
930                    NaiveDate::from_ymd_opt(2025, 8, 1).unwrap(),
931                )),
932                Some(Date32Type::from_naive_date(NaiveDate::MAX)),
933            ])),
934            vec![
935                Some(Variant::Date(NaiveDate::MIN)),
936                None,
937                Some(Variant::Date(NaiveDate::from_ymd_opt(2025, 8, 1).unwrap())),
938                Some(Variant::Date(NaiveDate::MAX)),
939            ],
940        );
941
942        // Date64Array
943        run_test(
944            Arc::new(Date64Array::from(vec![
945                Some(Date64Type::from_naive_date(NaiveDate::MIN)),
946                None,
947                Some(Date64Type::from_naive_date(
948                    NaiveDate::from_ymd_opt(2025, 8, 1).unwrap(),
949                )),
950                Some(Date64Type::from_naive_date(NaiveDate::MAX)),
951            ])),
952            vec![
953                Some(Variant::Date(NaiveDate::MIN)),
954                None,
955                Some(Variant::Date(NaiveDate::from_ymd_opt(2025, 8, 1).unwrap())),
956                Some(Variant::Date(NaiveDate::MAX)),
957            ],
958        );
959    }
960
961    #[test]
962    fn test_cast_to_variant_date64_strict_mode() {
963        let date64_values = Date64Array::from(vec![Some(i64::MAX), Some(0), Some(i64::MIN)]);
964
965        let values = Arc::new(date64_values);
966        run_test_in_strict_mode(
967            values,
968            Err(ArrowError::ComputeError(
969                "Failed to convert value at index 0: conversion failed".to_string(),
970            )),
971        );
972    }
973
974    #[test]
975    fn test_cast_to_variant_date64_non_strict_mode() {
976        let date64_values = Date64Array::from(vec![Some(i64::MAX), Some(0), Some(i64::MIN)]);
977
978        let values = Arc::new(date64_values);
979        run_test(
980            values,
981            vec![
982                Some(Variant::Null),
983                Some(Variant::Date(Date64Type::to_naive_date_opt(0).unwrap())),
984                Some(Variant::Null),
985            ],
986        );
987    }
988
989    #[test]
990    fn test_cast_to_variant_time32_second() {
991        let array: Time32SecondArray = vec![Some(1), Some(86_399), None].into();
992        let values = Arc::new(array);
993        run_test(
994            values,
995            vec![
996                Some(Variant::Time(
997                    NaiveTime::from_num_seconds_from_midnight_opt(1, 0).unwrap(),
998                )),
999                Some(Variant::Time(
1000                    NaiveTime::from_num_seconds_from_midnight_opt(86_399, 0).unwrap(),
1001                )),
1002                None,
1003            ],
1004        )
1005    }
1006
1007    #[test]
1008    fn test_cast_to_variant_time32_millisecond() {
1009        let array: Time32MillisecondArray = vec![Some(123_456), Some(456_000), None].into();
1010        let values = Arc::new(array);
1011        run_test(
1012            values,
1013            vec![
1014                Some(Variant::Time(
1015                    NaiveTime::from_num_seconds_from_midnight_opt(123, 456_000_000).unwrap(),
1016                )),
1017                Some(Variant::Time(
1018                    NaiveTime::from_num_seconds_from_midnight_opt(456, 0).unwrap(),
1019                )),
1020                None,
1021            ],
1022        )
1023    }
1024
1025    #[test]
1026    fn test_cast_to_variant_time64_micro() {
1027        let array: Time64MicrosecondArray = vec![Some(1), Some(123_456_789), None].into();
1028        let values = Arc::new(array);
1029        run_test(
1030            values,
1031            vec![
1032                Some(Variant::Time(
1033                    NaiveTime::from_num_seconds_from_midnight_opt(0, 1_000).unwrap(),
1034                )),
1035                Some(Variant::Time(
1036                    NaiveTime::from_num_seconds_from_midnight_opt(123, 456_789_000).unwrap(),
1037                )),
1038                None,
1039            ],
1040        )
1041    }
1042
1043    #[test]
1044    fn test_cast_to_variant_time64_nano() {
1045        let array: Time64NanosecondArray =
1046            vec![Some(1), Some(1001), Some(123_456_789_012), None].into();
1047        run_test(
1048            Arc::new(array),
1049            // as we can only present with micro second, so the nano second will round down to 0
1050            vec![
1051                Some(Variant::Time(
1052                    NaiveTime::from_num_seconds_from_midnight_opt(0, 0).unwrap(),
1053                )),
1054                Some(Variant::Time(
1055                    NaiveTime::from_num_seconds_from_midnight_opt(0, 1_000).unwrap(),
1056                )),
1057                Some(Variant::Time(
1058                    NaiveTime::from_num_seconds_from_midnight_opt(123, 456_789_000).unwrap(),
1059                )),
1060                None,
1061            ],
1062        )
1063    }
1064
1065    #[test]
1066    fn test_cast_to_variant_time32_strict_mode() {
1067        let time32_array = Time32SecondArray::from(vec![Some(90000), Some(3600), Some(-1)]);
1068
1069        let values = Arc::new(time32_array);
1070        run_test_in_strict_mode(
1071            values,
1072            Err(ArrowError::ComputeError(
1073                "Failed to convert value at index 0: conversion failed".to_string(),
1074            )),
1075        );
1076    }
1077
1078    #[test]
1079    fn test_cast_to_variant_time32_non_strict_mode() {
1080        let time32_array = Time32SecondArray::from(vec![Some(90000), Some(3600), Some(-1)]);
1081
1082        let values = Arc::new(time32_array);
1083        run_test(
1084            values,
1085            vec![
1086                Some(Variant::Null),
1087                Some(Variant::Time(
1088                    NaiveTime::from_num_seconds_from_midnight_opt(3600, 0).unwrap(),
1089                )),
1090                Some(Variant::Null),
1091            ],
1092        );
1093    }
1094
1095    #[test]
1096    fn test_cast_to_variant_duration_or_interval_errors() {
1097        let arrays: Vec<Box<dyn Array>> = vec![
1098            // Duration types
1099            Box::new(DurationSecondArray::from(vec![Some(10), None, Some(-5)])),
1100            Box::new(DurationMillisecondArray::from(vec![
1101                Some(10),
1102                None,
1103                Some(-5),
1104            ])),
1105            Box::new(DurationMicrosecondArray::from(vec![
1106                Some(10),
1107                None,
1108                Some(-5),
1109            ])),
1110            Box::new(DurationNanosecondArray::from(vec![
1111                Some(10),
1112                None,
1113                Some(-5),
1114            ])),
1115            // Interval types
1116            Box::new(IntervalYearMonthArray::from(vec![Some(12), None, Some(-6)])),
1117            Box::new(IntervalDayTimeArray::from(vec![
1118                Some(IntervalDayTime::new(12, 0)),
1119                None,
1120                Some(IntervalDayTime::new(-6, 0)),
1121            ])),
1122            Box::new(IntervalMonthDayNanoArray::from(vec![
1123                Some(IntervalMonthDayNano::new(12, 0, 0)),
1124                None,
1125                Some(IntervalMonthDayNano::new(-6, 0, 0)),
1126            ])),
1127        ];
1128
1129        for array in arrays {
1130            let result = cast_to_variant(array.as_ref());
1131            assert!(result.is_err());
1132            match result.unwrap_err() {
1133                ArrowError::InvalidArgumentError(msg) => {
1134                    assert!(
1135                        msg.contains("Casting duration/interval types to Variant is not supported")
1136                    );
1137                    assert!(
1138                        msg.contains("The Variant format does not define duration/interval types")
1139                    );
1140                }
1141                _ => panic!("Expected InvalidArgumentError"),
1142            }
1143        }
1144    }
1145
1146    #[test]
1147    fn test_cast_to_variant_binary() {
1148        // BinaryType
1149        let mut builder = GenericByteBuilder::<BinaryType>::new();
1150        builder.append_value(b"hello");
1151        builder.append_value(b"");
1152        builder.append_null();
1153        builder.append_value(b"world");
1154        let binary_array = builder.finish();
1155        run_test(
1156            Arc::new(binary_array),
1157            vec![
1158                Some(Variant::Binary(b"hello")),
1159                Some(Variant::Binary(b"")),
1160                None,
1161                Some(Variant::Binary(b"world")),
1162            ],
1163        );
1164
1165        // LargeBinaryType
1166        let mut builder = GenericByteBuilder::<LargeBinaryType>::new();
1167        builder.append_value(b"hello");
1168        builder.append_value(b"");
1169        builder.append_null();
1170        builder.append_value(b"world");
1171        let large_binary_array = builder.finish();
1172        run_test(
1173            Arc::new(large_binary_array),
1174            vec![
1175                Some(Variant::Binary(b"hello")),
1176                Some(Variant::Binary(b"")),
1177                None,
1178                Some(Variant::Binary(b"world")),
1179            ],
1180        );
1181
1182        // BinaryViewType
1183        let mut builder = GenericByteViewBuilder::<BinaryViewType>::new();
1184        builder.append_value(b"hello");
1185        builder.append_value(b"");
1186        builder.append_null();
1187        builder.append_value(b"world");
1188        let byte_view_array = builder.finish();
1189        run_test(
1190            Arc::new(byte_view_array),
1191            vec![
1192                Some(Variant::Binary(b"hello")),
1193                Some(Variant::Binary(b"")),
1194                None,
1195                Some(Variant::Binary(b"world")),
1196            ],
1197        );
1198    }
1199
1200    #[test]
1201    fn test_cast_to_variant_fixed_size_binary() {
1202        let v1 = vec![1, 2];
1203        let v2 = vec![3, 4];
1204        let v3 = vec![5, 6];
1205
1206        let mut builder = FixedSizeBinaryBuilder::new(2);
1207        builder.append_value(&v1).unwrap();
1208        builder.append_value(&v2).unwrap();
1209        builder.append_null();
1210        builder.append_value(&v3).unwrap();
1211        let array = builder.finish();
1212
1213        run_test(
1214            Arc::new(array),
1215            vec![
1216                Some(Variant::Binary(&v1)),
1217                Some(Variant::Binary(&v2)),
1218                None,
1219                Some(Variant::Binary(&v3)),
1220            ],
1221        );
1222    }
1223
1224    #[test]
1225    fn test_cast_to_variant_utf8() {
1226        // Test with short strings (should become ShortString variants)
1227        let short_strings = vec![Some("hello"), Some(""), None, Some("world"), Some("test")];
1228        let string_array = StringArray::from(short_strings.clone());
1229
1230        run_test(
1231            Arc::new(string_array),
1232            vec![
1233                Some(Variant::from("hello")),
1234                Some(Variant::from("")),
1235                None,
1236                Some(Variant::from("world")),
1237                Some(Variant::from("test")),
1238            ],
1239        );
1240
1241        // Test with a long string (should become String variant)
1242        let long_string = "a".repeat(100); // > 63 bytes, so will be Variant::String
1243        let long_strings = vec![Some(long_string.clone()), None, Some("short".to_string())];
1244        let string_array = StringArray::from(long_strings);
1245
1246        run_test(
1247            Arc::new(string_array),
1248            vec![
1249                Some(Variant::from(long_string.as_str())),
1250                None,
1251                Some(Variant::from("short")),
1252            ],
1253        );
1254    }
1255
1256    #[test]
1257    fn test_cast_to_variant_large_utf8() {
1258        // Test with short strings (should become ShortString variants)
1259        let short_strings = vec![Some("hello"), Some(""), None, Some("world")];
1260        let string_array = LargeStringArray::from(short_strings.clone());
1261
1262        run_test(
1263            Arc::new(string_array),
1264            vec![
1265                Some(Variant::from("hello")),
1266                Some(Variant::from("")),
1267                None,
1268                Some(Variant::from("world")),
1269            ],
1270        );
1271
1272        // Test with a long string (should become String variant)
1273        let long_string = "b".repeat(100); // > 63 bytes, so will be Variant::String
1274        let long_strings = vec![Some(long_string.clone()), None, Some("short".to_string())];
1275        let string_array = LargeStringArray::from(long_strings);
1276
1277        run_test(
1278            Arc::new(string_array),
1279            vec![
1280                Some(Variant::from(long_string.as_str())),
1281                None,
1282                Some(Variant::from("short")),
1283            ],
1284        );
1285    }
1286
1287    #[test]
1288    fn test_cast_to_variant_utf8_view() {
1289        // Test with short strings (should become ShortString variants)
1290        let short_strings = vec![Some("hello"), Some(""), None, Some("world")];
1291        let string_view_array = StringViewArray::from(short_strings.clone());
1292
1293        run_test(
1294            Arc::new(string_view_array),
1295            vec![
1296                Some(Variant::from("hello")),
1297                Some(Variant::from("")),
1298                None,
1299                Some(Variant::from("world")),
1300            ],
1301        );
1302
1303        // Test with a long string (should become String variant)
1304        let long_string = "c".repeat(100); // > 63 bytes, so will be Variant::String
1305        let long_strings = vec![Some(long_string.clone()), None, Some("short".to_string())];
1306        let string_view_array = StringViewArray::from(long_strings);
1307
1308        run_test(
1309            Arc::new(string_view_array),
1310            vec![
1311                Some(Variant::from(long_string.as_str())),
1312                None,
1313                Some(Variant::from("short")),
1314            ],
1315        );
1316    }
1317
1318    #[test]
1319    fn test_cast_to_variant_list() {
1320        // List Array
1321        let data = vec![Some(vec![Some(0), Some(1), Some(2)]), None];
1322        let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1323
1324        // Expected value
1325        let (metadata, value) = {
1326            let mut builder = VariantBuilder::new();
1327            let mut list = builder.new_list();
1328            list.append_value(0);
1329            list.append_value(1);
1330            list.append_value(2);
1331            list.finish();
1332            builder.finish()
1333        };
1334        let variant = Variant::new(&metadata, &value);
1335
1336        run_test(Arc::new(list_array), vec![Some(variant), None]);
1337    }
1338
1339    #[test]
1340    fn test_cast_to_variant_sliced_list() {
1341        // List Array
1342        let data = vec![
1343            Some(vec![Some(0), Some(1), Some(2)]),
1344            Some(vec![Some(3), Some(4), Some(5)]),
1345            None,
1346        ];
1347        let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1348
1349        // Expected value
1350        let (metadata, value) = {
1351            let mut builder = VariantBuilder::new();
1352            let mut list = builder.new_list();
1353            list.append_value(3);
1354            list.append_value(4);
1355            list.append_value(5);
1356            list.finish();
1357            builder.finish()
1358        };
1359        let variant = Variant::new(&metadata, &value);
1360
1361        run_test(Arc::new(list_array.slice(1, 2)), vec![Some(variant), None]);
1362    }
1363
1364    #[test]
1365    fn test_cast_to_variant_large_list() {
1366        // Large List Array
1367        let data = vec![Some(vec![Some(0), Some(1), Some(2)]), None];
1368        let large_list_array = LargeListArray::from_iter_primitive::<Int64Type, _, _>(data);
1369
1370        // Expected value
1371        let (metadata, value) = {
1372            let mut builder = VariantBuilder::new();
1373            let mut list = builder.new_list();
1374            list.append_value(0i64);
1375            list.append_value(1i64);
1376            list.append_value(2i64);
1377            list.finish();
1378            builder.finish()
1379        };
1380        let variant = Variant::new(&metadata, &value);
1381
1382        run_test(Arc::new(large_list_array), vec![Some(variant), None]);
1383    }
1384
1385    #[test]
1386    fn test_cast_to_variant_sliced_large_list() {
1387        // List Array
1388        let data = vec![
1389            Some(vec![Some(0), Some(1), Some(2)]),
1390            Some(vec![Some(3), Some(4), Some(5)]),
1391            None,
1392        ];
1393        let large_list_array = ListArray::from_iter_primitive::<Int64Type, _, _>(data);
1394
1395        // Expected value
1396        let (metadata, value) = {
1397            let mut builder = VariantBuilder::new();
1398            let mut list = builder.new_list();
1399            list.append_value(3i64);
1400            list.append_value(4i64);
1401            list.append_value(5i64);
1402            list.finish();
1403            builder.finish()
1404        };
1405        let variant = Variant::new(&metadata, &value);
1406
1407        run_test(
1408            Arc::new(large_list_array.slice(1, 2)),
1409            vec![Some(variant), None],
1410        );
1411    }
1412
1413    #[test]
1414    fn test_cast_to_variant_list_view() {
1415        // Create a ListViewArray with some data
1416        let mut builder = ListViewBuilder::new(Int32Array::builder(0));
1417        builder.append_value(&Int32Array::from(vec![Some(0), None, Some(2)]));
1418        builder.append_value(&Int32Array::from(vec![Some(3), Some(4)]));
1419        builder.append_null();
1420        builder.append_value(&Int32Array::from(vec![None, None]));
1421        let list_view_array = builder.finish();
1422
1423        // Expected values
1424        let (metadata, value) = {
1425            let mut builder = VariantBuilder::new();
1426            let mut list = builder.new_list();
1427            list.append_value(0i32);
1428            list.append_null();
1429            list.append_value(2i32);
1430            list.finish();
1431            builder.finish()
1432        };
1433        let variant0 = Variant::new(&metadata, &value);
1434
1435        let (metadata, value) = {
1436            let mut builder = VariantBuilder::new();
1437            let mut list = builder.new_list();
1438            list.append_value(3i32);
1439            list.append_value(4i32);
1440            list.finish();
1441            builder.finish()
1442        };
1443        let variant1 = Variant::new(&metadata, &value);
1444
1445        let (metadata, value) = {
1446            let mut builder = VariantBuilder::new();
1447            let mut list = builder.new_list();
1448            list.append_null();
1449            list.append_null();
1450            list.finish();
1451            builder.finish()
1452        };
1453        let variant3 = Variant::new(&metadata, &value);
1454
1455        run_test(
1456            Arc::new(list_view_array),
1457            vec![Some(variant0), Some(variant1), None, Some(variant3)],
1458        );
1459    }
1460
1461    #[test]
1462    fn test_cast_to_variant_sliced_list_view() {
1463        // Create a ListViewArray with some data
1464        let mut builder = ListViewBuilder::new(Int32Array::builder(0));
1465        builder.append_value(&Int32Array::from(vec![Some(0), Some(1), Some(2)]));
1466        builder.append_value(&Int32Array::from(vec![Some(3), None]));
1467        builder.append_null();
1468        let list_view_array = builder.finish();
1469
1470        // Expected value for slice(1, 2) - should get the second and third elements
1471        let (metadata, value) = {
1472            let mut builder = VariantBuilder::new();
1473            let mut list = builder.new_list();
1474            list.append_value(3i32);
1475            list.append_null();
1476            list.finish();
1477            builder.finish()
1478        };
1479        let variant = Variant::new(&metadata, &value);
1480
1481        run_test(
1482            Arc::new(list_view_array.slice(1, 2)),
1483            vec![Some(variant), None],
1484        );
1485    }
1486
1487    #[test]
1488    fn test_cast_to_variant_large_list_view() {
1489        // Create a LargeListViewArray with some data
1490        let mut builder = LargeListViewBuilder::new(Int64Array::builder(0));
1491        builder.append_value(&Int64Array::from(vec![Some(0), None, Some(2)]));
1492        builder.append_value(&Int64Array::from(vec![Some(3), Some(4)]));
1493        builder.append_null();
1494        builder.append_value(&Int64Array::from(vec![None, None]));
1495        let large_list_view_array = builder.finish();
1496
1497        // Expected values
1498        let (metadata, value) = {
1499            let mut builder = VariantBuilder::new();
1500            let mut list = builder.new_list();
1501            list.append_value(0i64);
1502            list.append_null();
1503            list.append_value(2i64);
1504            list.finish();
1505            builder.finish()
1506        };
1507        let variant0 = Variant::new(&metadata, &value);
1508
1509        let (metadata, value) = {
1510            let mut builder = VariantBuilder::new();
1511            let mut list = builder.new_list();
1512            list.append_value(3i64);
1513            list.append_value(4i64);
1514            list.finish();
1515            builder.finish()
1516        };
1517        let variant1 = Variant::new(&metadata, &value);
1518
1519        let (metadata, value) = {
1520            let mut builder = VariantBuilder::new();
1521            let mut list = builder.new_list();
1522            list.append_null();
1523            list.append_null();
1524            list.finish();
1525            builder.finish()
1526        };
1527        let variant3 = Variant::new(&metadata, &value);
1528
1529        run_test(
1530            Arc::new(large_list_view_array),
1531            vec![Some(variant0), Some(variant1), None, Some(variant3)],
1532        );
1533    }
1534
1535    #[test]
1536    fn test_cast_to_variant_sliced_large_list_view() {
1537        // Create a LargeListViewArray with some data
1538        let mut builder = LargeListViewBuilder::new(Int64Array::builder(0));
1539        builder.append_value(&Int64Array::from(vec![Some(0), Some(1), Some(2)]));
1540        builder.append_value(&Int64Array::from(vec![Some(3), None]));
1541        builder.append_null();
1542        let large_list_view_array = builder.finish();
1543
1544        // Expected value for slice(1, 2) - should get the second and third elements
1545        let (metadata, value) = {
1546            let mut builder = VariantBuilder::new();
1547            let mut list = builder.new_list();
1548            list.append_value(3i64);
1549            list.append_null();
1550            list.finish();
1551            builder.finish()
1552        };
1553        let variant = Variant::new(&metadata, &value);
1554
1555        run_test(
1556            Arc::new(large_list_view_array.slice(1, 2)),
1557            vec![Some(variant), None],
1558        );
1559    }
1560
1561    #[test]
1562    fn test_cast_to_variant_fixed_size_list() {
1563        let mut builder = FixedSizeListBuilder::new(Int32Array::builder(0), 2);
1564        builder.values().append_value(0);
1565        builder.values().append_value(1);
1566        builder.append(true); // First list: [0, 1]
1567
1568        builder.values().append_null();
1569        builder.values().append_value(3);
1570        builder.append(true); // Second list: [null, 3]
1571
1572        builder.values().append_value(4);
1573        builder.values().append_null();
1574        builder.append(false); // Third list: null
1575
1576        builder.values().append_nulls(2);
1577        builder.append(true); // Last list: [null, null]
1578
1579        let fixed_size_list_array = builder.finish();
1580
1581        // Expected values
1582        let (metadata, value) = {
1583            let mut builder = VariantBuilder::new();
1584            let mut list = builder.new_list();
1585            list.append_value(0i32);
1586            list.append_value(1i32);
1587            list.finish();
1588            builder.finish()
1589        };
1590        let variant0 = Variant::new(&metadata, &value);
1591
1592        let (metadata, value) = {
1593            let mut builder = VariantBuilder::new();
1594            let mut list = builder.new_list();
1595            list.append_null();
1596            list.append_value(3i32);
1597            list.finish();
1598            builder.finish()
1599        };
1600        let variant1 = Variant::new(&metadata, &value);
1601
1602        let (metadata, value) = {
1603            let mut builder = VariantBuilder::new();
1604            let mut list = builder.new_list();
1605            list.append_null();
1606            list.append_null();
1607            list.finish();
1608            builder.finish()
1609        };
1610        let variant3 = Variant::new(&metadata, &value);
1611
1612        run_test(
1613            Arc::new(fixed_size_list_array),
1614            vec![Some(variant0), Some(variant1), None, Some(variant3)],
1615        );
1616    }
1617
1618    #[test]
1619    fn test_cast_to_variant_sliced_fixed_size_list() {
1620        // Create a FixedSizeListArray with size 2
1621        let mut builder = FixedSizeListBuilder::new(Int64Array::builder(0), 2);
1622        builder.values().append_value(0);
1623        builder.values().append_value(1);
1624        builder.append(true); // First list: [0, 1]
1625
1626        builder.values().append_null();
1627        builder.values().append_value(3);
1628        builder.append(true); // Second list: [null, 3]
1629
1630        builder.values().append_value(4);
1631        builder.values().append_null();
1632        builder.append(false); // Third list: null
1633
1634        let fixed_size_list_array = builder.finish();
1635
1636        // Expected value for slice(1, 2) - should get the second and third elements
1637        let (metadata, value) = {
1638            let mut builder = VariantBuilder::new();
1639            let mut list = builder.new_list();
1640            list.append_null();
1641            list.append_value(3i64);
1642            list.finish();
1643            builder.finish()
1644        };
1645        let variant = Variant::new(&metadata, &value);
1646
1647        run_test(
1648            Arc::new(fixed_size_list_array.slice(1, 2)),
1649            vec![Some(variant), None],
1650        );
1651    }
1652
1653    #[test]
1654    fn test_cast_to_variant_struct() {
1655        // Test a simple struct with two fields: id (int64) and age (int32)
1656        let id_array = Int64Array::from(vec![Some(1001), Some(1002), None, Some(1003)]);
1657        let age_array = Int32Array::from(vec![Some(25), Some(30), Some(35), None]);
1658
1659        let fields = Fields::from(vec![
1660            Field::new("id", DataType::Int64, true),
1661            Field::new("age", DataType::Int32, true),
1662        ]);
1663
1664        let struct_array = StructArray::new(
1665            fields,
1666            vec![Arc::new(id_array), Arc::new(age_array)],
1667            None, // no nulls at the struct level
1668        );
1669
1670        let result = cast_to_variant(&struct_array).unwrap();
1671        assert_eq!(result.len(), 4);
1672
1673        // Check first row: {"id": 1001, "age": 25}
1674        let variant1 = result.value(0);
1675        let obj1 = variant1.as_object().unwrap();
1676        assert_eq!(obj1.get("id"), Some(Variant::from(1001i64)));
1677        assert_eq!(obj1.get("age"), Some(Variant::from(25i32)));
1678
1679        // Check second row: {"id": 1002, "age": 30}
1680        let variant2 = result.value(1);
1681        let obj2 = variant2.as_object().unwrap();
1682        assert_eq!(obj2.get("id"), Some(Variant::from(1002i64)));
1683        assert_eq!(obj2.get("age"), Some(Variant::from(30i32)));
1684
1685        // Check third row: {"age": 35} (id is null, so omitted)
1686        let variant3 = result.value(2);
1687        let obj3 = variant3.as_object().unwrap();
1688        assert_eq!(obj3.get("id"), None);
1689        assert_eq!(obj3.get("age"), Some(Variant::from(35i32)));
1690
1691        // Check fourth row: {"id": 1003} (age is null, so omitted)
1692        let variant4 = result.value(3);
1693        let obj4 = variant4.as_object().unwrap();
1694        assert_eq!(obj4.get("id"), Some(Variant::from(1003i64)));
1695        assert_eq!(obj4.get("age"), None);
1696    }
1697
1698    #[test]
1699    fn test_cast_to_variant_struct_with_nulls() {
1700        // Test struct with null values at the struct level
1701        let id_array = Int64Array::from(vec![Some(1001), Some(1002)]);
1702        let age_array = Int32Array::from(vec![Some(25), Some(30)]);
1703
1704        let fields = Fields::from(vec![
1705            Field::new("id", DataType::Int64, false),
1706            Field::new("age", DataType::Int32, false),
1707        ]);
1708
1709        // Create null buffer to make second row null
1710        let null_buffer = NullBuffer::from(vec![true, false]);
1711
1712        let struct_array = StructArray::new(
1713            fields,
1714            vec![Arc::new(id_array), Arc::new(age_array)],
1715            Some(null_buffer),
1716        );
1717
1718        let result = cast_to_variant(&struct_array).unwrap();
1719        assert_eq!(result.len(), 2);
1720
1721        // Check first row: {"id": 1001, "age": 25}
1722        assert!(!result.is_null(0));
1723        let variant1 = result.value(0);
1724        let obj1 = variant1.as_object().unwrap();
1725        assert_eq!(obj1.get("id"), Some(Variant::from(1001i64)));
1726        assert_eq!(obj1.get("age"), Some(Variant::from(25i32)));
1727
1728        // Check second row: null struct
1729        assert!(result.is_null(1));
1730    }
1731
1732    #[test]
1733    fn test_cast_to_variant_struct_performance() {
1734        // Test with a larger struct to demonstrate performance optimization
1735        // This test ensures that field arrays are only converted once, not per row
1736        let size = 1000;
1737
1738        let id_array = Int64Array::from((0..size).map(|i| Some(i as i64)).collect::<Vec<_>>());
1739        let age_array = Int32Array::from(
1740            (0..size)
1741                .map(|i| Some((i % 100) as i32))
1742                .collect::<Vec<_>>(),
1743        );
1744        let score_array =
1745            Float64Array::from((0..size).map(|i| Some(i as f64 * 0.1)).collect::<Vec<_>>());
1746
1747        let fields = Fields::from(vec![
1748            Field::new("id", DataType::Int64, false),
1749            Field::new("age", DataType::Int32, false),
1750            Field::new("score", DataType::Float64, false),
1751        ]);
1752
1753        let struct_array = StructArray::new(
1754            fields,
1755            vec![
1756                Arc::new(id_array),
1757                Arc::new(age_array),
1758                Arc::new(score_array),
1759            ],
1760            None,
1761        );
1762
1763        let result = cast_to_variant(&struct_array).unwrap();
1764        assert_eq!(result.len(), size);
1765
1766        // Verify a few sample rows
1767        let variant0 = result.value(0);
1768        let obj0 = variant0.as_object().unwrap();
1769        assert_eq!(obj0.get("id"), Some(Variant::from(0i64)));
1770        assert_eq!(obj0.get("age"), Some(Variant::from(0i32)));
1771        assert_eq!(obj0.get("score"), Some(Variant::from(0.0f64)));
1772
1773        let variant999 = result.value(999);
1774        let obj999 = variant999.as_object().unwrap();
1775        assert_eq!(obj999.get("id"), Some(Variant::from(999i64)));
1776        assert_eq!(obj999.get("age"), Some(Variant::from(99i32))); // 999 % 100 = 99
1777        assert_eq!(obj999.get("score"), Some(Variant::from(99.9f64)));
1778    }
1779
1780    #[test]
1781    fn test_cast_to_variant_struct_performance_large() {
1782        // Test with even larger struct and more fields to demonstrate optimization benefits
1783        let size = 10000;
1784        let num_fields = 10;
1785
1786        // Create arrays for many fields
1787        let mut field_arrays: Vec<ArrayRef> = Vec::new();
1788        let mut fields = Vec::new();
1789
1790        for field_idx in 0..num_fields {
1791            match field_idx % 4 {
1792                0 => {
1793                    // Int64 fields
1794                    let array = Int64Array::from(
1795                        (0..size)
1796                            .map(|i| Some(i as i64 + field_idx as i64))
1797                            .collect::<Vec<_>>(),
1798                    );
1799                    field_arrays.push(Arc::new(array));
1800                    fields.push(Field::new(
1801                        format!("int_field_{field_idx}"),
1802                        DataType::Int64,
1803                        false,
1804                    ));
1805                }
1806                1 => {
1807                    // Int32 fields
1808                    let array = Int32Array::from(
1809                        (0..size)
1810                            .map(|i| Some((i % 1000) as i32 + field_idx as i32))
1811                            .collect::<Vec<_>>(),
1812                    );
1813                    field_arrays.push(Arc::new(array));
1814                    fields.push(Field::new(
1815                        format!("int32_field_{field_idx}"),
1816                        DataType::Int32,
1817                        false,
1818                    ));
1819                }
1820                2 => {
1821                    // Float64 fields
1822                    let array = Float64Array::from(
1823                        (0..size)
1824                            .map(|i| Some(i as f64 * 0.1 + field_idx as f64))
1825                            .collect::<Vec<_>>(),
1826                    );
1827                    field_arrays.push(Arc::new(array));
1828                    fields.push(Field::new(
1829                        format!("float_field_{field_idx}"),
1830                        DataType::Float64,
1831                        false,
1832                    ));
1833                }
1834                _ => {
1835                    // Binary fields
1836                    let binary_data: Vec<Option<&[u8]>> = (0..size)
1837                        .map(|i| {
1838                            // Use static data to avoid lifetime issues in tests
1839                            match i % 3 {
1840                                0 => Some(b"test_data_0" as &[u8]),
1841                                1 => Some(b"test_data_1" as &[u8]),
1842                                _ => Some(b"test_data_2" as &[u8]),
1843                            }
1844                        })
1845                        .collect();
1846                    let array = BinaryArray::from(binary_data);
1847                    field_arrays.push(Arc::new(array));
1848                    fields.push(Field::new(
1849                        format!("binary_field_{field_idx}"),
1850                        DataType::Binary,
1851                        false,
1852                    ));
1853                }
1854            }
1855        }
1856
1857        let struct_array = StructArray::new(Fields::from(fields), field_arrays, None);
1858
1859        let result = cast_to_variant(&struct_array).unwrap();
1860        assert_eq!(result.len(), size);
1861
1862        // Verify a sample of rows
1863        for sample_idx in [0, size / 4, size / 2, size - 1] {
1864            let variant = result.value(sample_idx);
1865            let obj = variant.as_object().unwrap();
1866
1867            // Should have all fields
1868            assert_eq!(obj.len(), num_fields);
1869
1870            // Verify a few field values
1871            if let Some(int_field_0) = obj.get("int_field_0") {
1872                assert_eq!(int_field_0, Variant::from(sample_idx as i64));
1873            }
1874            if let Some(float_field_2) = obj.get("float_field_2") {
1875                assert_eq!(float_field_2, Variant::from(sample_idx as f64 * 0.1 + 2.0));
1876            }
1877        }
1878    }
1879
1880    #[test]
1881    fn test_cast_to_variant_nested_struct() {
1882        // Test nested struct: person with location struct
1883        let id_array = Int64Array::from(vec![Some(1001), Some(1002)]);
1884        let x_array = Float64Array::from(vec![Some(40.7), Some(37.8)]);
1885        let y_array = Float64Array::from(vec![Some(-74.0), Some(-122.4)]);
1886
1887        // Create location struct
1888        let location_fields = Fields::from(vec![
1889            Field::new("x", DataType::Float64, true),
1890            Field::new("y", DataType::Float64, true),
1891        ]);
1892        let location_struct = StructArray::new(
1893            location_fields.clone(),
1894            vec![Arc::new(x_array), Arc::new(y_array)],
1895            None,
1896        );
1897
1898        // Create person struct containing location
1899        let person_fields = Fields::from(vec![
1900            Field::new("id", DataType::Int64, true),
1901            Field::new("location", DataType::Struct(location_fields), true),
1902        ]);
1903        let person_struct = StructArray::new(
1904            person_fields,
1905            vec![Arc::new(id_array), Arc::new(location_struct)],
1906            None,
1907        );
1908
1909        let result = cast_to_variant(&person_struct).unwrap();
1910        assert_eq!(result.len(), 2);
1911
1912        // Check first row
1913        let variant1 = result.value(0);
1914        let obj1 = variant1.as_object().unwrap();
1915        assert_eq!(obj1.get("id"), Some(Variant::from(1001i64)));
1916
1917        let location_variant1 = obj1.get("location").unwrap();
1918        let location_obj1 = location_variant1.as_object().unwrap();
1919        assert_eq!(location_obj1.get("x"), Some(Variant::from(40.7f64)));
1920        assert_eq!(location_obj1.get("y"), Some(Variant::from(-74.0f64)));
1921
1922        // Check second row
1923        let variant2 = result.value(1);
1924        let obj2 = variant2.as_object().unwrap();
1925        assert_eq!(obj2.get("id"), Some(Variant::from(1002i64)));
1926
1927        let location_variant2 = obj2.get("location").unwrap();
1928        let location_obj2 = location_variant2.as_object().unwrap();
1929        assert_eq!(location_obj2.get("x"), Some(Variant::from(37.8f64)));
1930        assert_eq!(location_obj2.get("y"), Some(Variant::from(-122.4f64)));
1931    }
1932
1933    #[test]
1934    fn test_cast_to_variant_map() {
1935        let keys = vec!["key1", "key2", "key3"];
1936        let values_data = Int32Array::from(vec![1, 2, 3]);
1937        let entry_offsets = vec![0, 1, 3];
1938        let map_array =
1939            MapArray::new_from_strings(keys.clone().into_iter(), &values_data, &entry_offsets)
1940                .unwrap();
1941
1942        let result = cast_to_variant(&map_array).unwrap();
1943        // [{"key1":1}]
1944        let variant1 = result.value(0);
1945        assert_eq!(
1946            variant1.as_object().unwrap().get("key1").unwrap(),
1947            Variant::from(1)
1948        );
1949
1950        // [{"key2":2},{"key3":3}]
1951        let variant2 = result.value(1);
1952        assert_eq!(
1953            variant2.as_object().unwrap().get("key2").unwrap(),
1954            Variant::from(2)
1955        );
1956        assert_eq!(
1957            variant2.as_object().unwrap().get("key3").unwrap(),
1958            Variant::from(3)
1959        );
1960    }
1961
1962    #[test]
1963    fn test_cast_to_variant_map_with_nulls_and_empty() {
1964        use arrow::array::{Int32Array, MapArray, StringArray, StructArray};
1965        use arrow::buffer::{NullBuffer, OffsetBuffer};
1966        use arrow::datatypes::{DataType, Field, Fields};
1967        use std::sync::Arc;
1968
1969        // Create entries struct array
1970        let keys = StringArray::from(vec!["key1", "key2", "key3"]);
1971        let values = Int32Array::from(vec![1, 2, 3]);
1972        let entries_fields = Fields::from(vec![
1973            Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, false),
1974            Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, true),
1975        ]);
1976        let entries = StructArray::new(
1977            entries_fields.clone(),
1978            vec![Arc::new(keys), Arc::new(values)],
1979            None,
1980        );
1981
1982        // Create offsets for 4 maps: [0..1], [1..1], [1..1], [1..3]
1983        let offsets = OffsetBuffer::new(vec![0, 1, 1, 1, 3].into());
1984
1985        // Create null buffer - map at index 2 is NULL
1986        let null_buffer = Some(NullBuffer::from(vec![true, true, false, true]));
1987
1988        let map_field = Arc::new(Field::new(
1989            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
1990            DataType::Struct(entries_fields),
1991            false,
1992        ));
1993
1994        let map_array = MapArray::try_new(map_field, offsets, entries, null_buffer, false).unwrap();
1995
1996        let result = cast_to_variant(&map_array).unwrap();
1997
1998        // Map 0: {"key1": 1}
1999        let variant0 = result.value(0);
2000        assert_eq!(
2001            variant0.as_object().unwrap().get("key1").unwrap(),
2002            Variant::from(1)
2003        );
2004
2005        // Map 1: {} (empty, not null)
2006        let variant1 = result.value(1);
2007        let obj1 = variant1.as_object().unwrap();
2008        assert_eq!(obj1.len(), 0); // Empty object
2009
2010        // Map 2: null (actual NULL)
2011        assert!(result.is_null(2));
2012
2013        // Map 3: {"key2": 2, "key3": 3}
2014        let variant3 = result.value(3);
2015        assert_eq!(
2016            variant3.as_object().unwrap().get("key2").unwrap(),
2017            Variant::from(2)
2018        );
2019        assert_eq!(
2020            variant3.as_object().unwrap().get("key3").unwrap(),
2021            Variant::from(3)
2022        );
2023    }
2024
2025    #[test]
2026    fn test_cast_to_variant_map_with_non_string_keys() {
2027        let offsets = OffsetBuffer::new(vec![0, 1, 3].into());
2028        let fields = Fields::from(vec![
2029            Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Int32, false),
2030            Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, false),
2031        ]);
2032        let columns = vec![
2033            Arc::new(Int32Array::from(vec![1, 2, 3])) as _,
2034            Arc::new(Int32Array::from(vec![1, 2, 3])) as _,
2035        ];
2036
2037        let entries = StructArray::new(fields.clone(), columns, None);
2038        let field = Arc::new(Field::new(
2039            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
2040            DataType::Struct(fields),
2041            false,
2042        ));
2043
2044        let map_array = MapArray::new(field.clone(), offsets.clone(), entries.clone(), None, false);
2045
2046        let result = cast_to_variant(&map_array).unwrap();
2047
2048        let variant1 = result.value(0);
2049        assert_eq!(
2050            variant1.as_object().unwrap().get("1").unwrap(),
2051            Variant::from(1)
2052        );
2053
2054        let variant2 = result.value(1);
2055        assert_eq!(
2056            variant2.as_object().unwrap().get("2").unwrap(),
2057            Variant::from(2)
2058        );
2059        assert_eq!(
2060            variant2.as_object().unwrap().get("3").unwrap(),
2061            Variant::from(3)
2062        );
2063    }
2064
2065    #[test]
2066    fn test_cast_to_variant_union_sparse() {
2067        // Create a sparse union array with mixed types (int, float, string)
2068        let int_array = Int32Array::from(vec![Some(1), None, None, None, Some(34), None]);
2069        let float_array = Float64Array::from(vec![None, Some(3.2), None, Some(32.5), None, None]);
2070        let string_array = StringArray::from(vec![None, None, Some("hello"), None, None, None]);
2071        let type_ids = [0, 1, 2, 1, 0, 0].into_iter().collect::<ScalarBuffer<i8>>();
2072
2073        let union_fields = UnionFields::from_fields(vec![
2074            Field::new("int_field", DataType::Int32, false),
2075            Field::new("float_field", DataType::Float64, false),
2076            Field::new("string_field", DataType::Utf8, false),
2077        ]);
2078
2079        let children: Vec<Arc<dyn Array>> = vec![
2080            Arc::new(int_array),
2081            Arc::new(float_array),
2082            Arc::new(string_array),
2083        ];
2084
2085        let union_array = UnionArray::try_new(
2086            union_fields,
2087            type_ids,
2088            None, // Sparse union
2089            children,
2090        )
2091        .unwrap();
2092
2093        run_test(
2094            Arc::new(union_array),
2095            vec![
2096                Some(Variant::Int32(1)),
2097                Some(Variant::Double(3.2)),
2098                Some(Variant::from("hello")),
2099                Some(Variant::Double(32.5)),
2100                Some(Variant::Int32(34)),
2101                None,
2102            ],
2103        );
2104    }
2105
2106    #[test]
2107    fn test_cast_to_variant_union_dense() {
2108        // Create a dense union array with mixed types (int, float, string)
2109        let int_array = Int32Array::from(vec![Some(1), Some(34), None]);
2110        let float_array = Float64Array::from(vec![3.2, 32.5]);
2111        let string_array = StringArray::from(vec!["hello"]);
2112        let type_ids = [0, 1, 2, 1, 0, 0].into_iter().collect::<ScalarBuffer<i8>>();
2113        let offsets = [0, 0, 0, 1, 1, 2]
2114            .into_iter()
2115            .collect::<ScalarBuffer<i32>>();
2116
2117        let union_fields = UnionFields::from_fields(vec![
2118            Field::new("int_field", DataType::Int32, false),
2119            Field::new("float_field", DataType::Float64, false),
2120            Field::new("string_field", DataType::Utf8, false),
2121        ]);
2122
2123        let children: Vec<Arc<dyn Array>> = vec![
2124            Arc::new(int_array),
2125            Arc::new(float_array),
2126            Arc::new(string_array),
2127        ];
2128
2129        let union_array = UnionArray::try_new(
2130            union_fields,
2131            type_ids,
2132            Some(offsets), // Dense union
2133            children,
2134        )
2135        .unwrap();
2136
2137        run_test(
2138            Arc::new(union_array),
2139            vec![
2140                Some(Variant::Int32(1)),
2141                Some(Variant::Double(3.2)),
2142                Some(Variant::from("hello")),
2143                Some(Variant::Double(32.5)),
2144                Some(Variant::Int32(34)),
2145                None,
2146            ],
2147        );
2148    }
2149
2150    #[test]
2151    fn test_cast_to_variant_dictionary() {
2152        let values = StringArray::from(vec!["apple", "banana", "cherry", "date"]);
2153        let keys = Int32Array::from(vec![Some(0), Some(1), None, Some(2), Some(0), Some(3)]);
2154        let dict_array = DictionaryArray::<Int32Type>::try_new(keys, Arc::new(values)).unwrap();
2155
2156        run_test(
2157            Arc::new(dict_array),
2158            vec![
2159                Some(Variant::from("apple")),
2160                Some(Variant::from("banana")),
2161                None,
2162                Some(Variant::from("cherry")),
2163                Some(Variant::from("apple")),
2164                Some(Variant::from("date")),
2165            ],
2166        );
2167    }
2168
2169    #[test]
2170    fn test_cast_to_variant_dictionary_with_nulls() {
2171        // Test dictionary with null values in the values array
2172        let values = StringArray::from(vec![Some("a"), None, Some("c")]);
2173        let keys = Int8Array::from(vec![Some(0), Some(1), Some(2), Some(0)]);
2174        let dict_array = DictionaryArray::<Int8Type>::try_new(keys, Arc::new(values)).unwrap();
2175
2176        run_test(
2177            Arc::new(dict_array),
2178            vec![
2179                Some(Variant::from("a")),
2180                None, // key 1 points to null value
2181                Some(Variant::from("c")),
2182                Some(Variant::from("a")),
2183            ],
2184        );
2185    }
2186
2187    #[test]
2188    fn test_cast_to_variant_run_end_encoded() {
2189        let mut builder = StringRunBuilder::<Int32Type>::new();
2190        builder.append_value("apple");
2191        builder.append_value("apple");
2192        builder.append_value("banana");
2193        builder.append_value("banana");
2194        builder.append_value("banana");
2195        builder.append_value("cherry");
2196        let run_array = builder.finish();
2197
2198        run_test(
2199            Arc::new(run_array),
2200            vec![
2201                Some(Variant::from("apple")),
2202                Some(Variant::from("apple")),
2203                Some(Variant::from("banana")),
2204                Some(Variant::from("banana")),
2205                Some(Variant::from("banana")),
2206                Some(Variant::from("cherry")),
2207            ],
2208        );
2209    }
2210
2211    #[test]
2212    fn test_cast_to_variant_run_end_encoded_with_nulls() {
2213        use arrow::array::StringRunBuilder;
2214        use arrow::datatypes::Int32Type;
2215
2216        // Test run-end encoded array with nulls
2217        let mut builder = StringRunBuilder::<Int32Type>::new();
2218        builder.append_value("apple");
2219        builder.append_null();
2220        builder.append_value("banana");
2221        builder.append_value("banana");
2222        builder.append_null();
2223        builder.append_null();
2224        let run_array = builder.finish();
2225
2226        run_test(
2227            Arc::new(run_array),
2228            vec![
2229                Some(Variant::from("apple")),
2230                None,
2231                Some(Variant::from("banana")),
2232                Some(Variant::from("banana")),
2233                None,
2234                None,
2235            ],
2236        );
2237    }
2238
2239    /// Converts the given `Array` to a `VariantArray` and tests the conversion
2240    /// against the expected values. It also tests the handling of nulls by
2241    /// setting one element to null and verifying the output.
2242    fn run_test_with_options(
2243        values: ArrayRef,
2244        expected: Vec<Option<Variant>>,
2245        options: CastOptions,
2246    ) {
2247        let variant_array = cast_to_variant_with_options(&values, &options).unwrap();
2248        assert_eq!(variant_array.len(), expected.len());
2249        for (i, expected_value) in expected.iter().enumerate() {
2250            match expected_value {
2251                Some(value) => {
2252                    assert!(!variant_array.is_null(i), "Expected non-null at index {i}");
2253                    assert_eq!(variant_array.value(i), *value, "mismatch at index {i}");
2254                }
2255                None => {
2256                    assert!(variant_array.is_null(i), "Expected null at index {i}");
2257                }
2258            }
2259        }
2260    }
2261
2262    fn run_test(values: ArrayRef, expected: Vec<Option<Variant>>) {
2263        run_test_with_options(values, expected, CastOptions::default());
2264    }
2265
2266    fn run_test_in_strict_mode(
2267        values: ArrayRef,
2268        expected: Result<Vec<Option<Variant>>, ArrowError>,
2269    ) {
2270        let options = CastOptions {
2271            safe: false,
2272            ..Default::default()
2273        };
2274        match expected {
2275            Ok(expected) => run_test_with_options(values, expected, options),
2276            Err(_) => {
2277                let result = cast_to_variant_with_options(values.as_ref(), &options);
2278                assert!(result.is_err());
2279                assert_eq!(
2280                    result.unwrap_err().to_string(),
2281                    expected.unwrap_err().to_string()
2282                );
2283            }
2284        }
2285    }
2286}