1use std::ops::Deref;
19use std::sync::Arc;
20
21use crate::{ArrowError, DataType, Field, FieldRef};
22
23#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59#[cfg_attr(feature = "serde", serde(transparent))]
60pub struct Fields(Arc<[FieldRef]>);
61
62impl std::fmt::Debug for Fields {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 self.0.as_ref().fmt(f)
65 }
66}
67
68impl Fields {
69 pub fn empty() -> Self {
71 Self(Arc::new([]))
72 }
73
74 pub fn size(&self) -> usize {
76 self.iter()
77 .map(|field| field.size() + std::mem::size_of::<FieldRef>())
78 .sum()
79 }
80
81 pub fn find(&self, name: &str) -> Option<(usize, &FieldRef)> {
83 self.0.iter().enumerate().find(|(_, b)| b.name() == name)
84 }
85
86 pub fn contains(&self, other: &Fields) -> bool {
93 if Arc::ptr_eq(&self.0, &other.0) {
94 return true;
95 }
96 self.len() == other.len()
97 && self
98 .iter()
99 .zip(other.iter())
100 .all(|(a, b)| Arc::ptr_eq(a, b) || a.contains(b))
101 }
102
103 pub fn filter_leaves<F: FnMut(usize, &FieldRef) -> bool>(&self, mut filter: F) -> Self {
140 self.try_filter_leaves(|idx, field| Ok(filter(idx, field)))
141 .unwrap()
142 }
143
144 pub fn try_filter_leaves<F: FnMut(usize, &FieldRef) -> Result<bool, ArrowError>>(
149 &self,
150 mut filter: F,
151 ) -> Result<Self, ArrowError> {
152 fn filter_field<F: FnMut(&FieldRef) -> Result<bool, ArrowError>>(
153 f: &FieldRef,
154 filter: &mut F,
155 ) -> Result<Option<FieldRef>, ArrowError> {
156 use DataType::*;
157
158 let v = match f.data_type() {
159 Dictionary(_, v) => v.as_ref(), RunEndEncoded(_, v) => v.data_type(), d => d,
162 };
163 let d = match v {
164 List(child) => {
165 let fields = filter_field(child, filter)?;
166 if let Some(fields) = fields {
167 List(fields)
168 } else {
169 return Ok(None);
170 }
171 }
172 LargeList(child) => {
173 let fields = filter_field(child, filter)?;
174 if let Some(fields) = fields {
175 LargeList(fields)
176 } else {
177 return Ok(None);
178 }
179 }
180 ListView(child) => {
181 let fields = filter_field(child, filter)?;
182 if let Some(fields) = fields {
183 ListView(fields)
184 } else {
185 return Ok(None);
186 }
187 }
188 LargeListView(child) => {
189 let fields = filter_field(child, filter)?;
190 if let Some(fields) = fields {
191 LargeListView(fields)
192 } else {
193 return Ok(None);
194 }
195 }
196 Map(child, ordered) => {
197 let fields = filter_field(child, filter)?;
198 if let Some(fields) = fields {
199 Map(fields, *ordered)
200 } else {
201 return Ok(None);
202 }
203 }
204 FixedSizeList(child, size) => {
205 let fields = filter_field(child, filter)?;
206 if let Some(fields) = fields {
207 FixedSizeList(fields, *size)
208 } else {
209 return Ok(None);
210 }
211 }
212 Struct(fields) => {
213 let filtered: Result<Vec<_>, _> =
214 fields.iter().map(|f| filter_field(f, filter)).collect();
215 let filtered: Fields = filtered?.iter().filter_map(|f| f.clone()).collect();
216
217 if filtered.is_empty() {
218 return Ok(None);
219 }
220
221 Struct(filtered)
222 }
223 Union(fields, mode) => {
224 let filtered: Result<Vec<_>, _> = fields
225 .iter()
226 .map(|(id, f)| filter_field(f, filter).map(|f| f.map(|f| (id, f))))
227 .collect();
228 let filtered: UnionFields =
229 filtered?.iter().filter_map(|f| f.clone()).collect();
230
231 if filtered.is_empty() {
232 return Ok(None);
233 }
234
235 Union(filtered, *mode)
236 }
237 _ => {
238 let filtered = filter(f)?;
239 return Ok(filtered.then(|| f.clone()));
240 }
241 };
242 let d = match f.data_type() {
243 Dictionary(k, _) => Dictionary(k.clone(), Box::new(d)),
244 RunEndEncoded(v, f) => {
245 RunEndEncoded(v.clone(), Arc::new(f.as_ref().clone().with_data_type(d)))
246 }
247 _ => d,
248 };
249 Ok(Some(Arc::new(f.as_ref().clone().with_data_type(d))))
250 }
251
252 let mut leaf_idx = 0;
253 let mut filter = |f: &FieldRef| {
254 let t = filter(leaf_idx, f)?;
255 leaf_idx += 1;
256 Ok(t)
257 };
258
259 let filtered: Result<Vec<_>, _> = self
260 .0
261 .iter()
262 .map(|f| filter_field(f, &mut filter))
263 .collect();
264 let filtered = filtered?.iter().filter_map(|f| f.clone()).collect();
265 Ok(filtered)
266 }
267}
268
269impl Default for Fields {
270 fn default() -> Self {
271 Self::empty()
272 }
273}
274
275impl FromIterator<Field> for Fields {
276 fn from_iter<T: IntoIterator<Item = Field>>(iter: T) -> Self {
277 iter.into_iter().map(Arc::new).collect()
278 }
279}
280
281impl FromIterator<FieldRef> for Fields {
282 fn from_iter<T: IntoIterator<Item = FieldRef>>(iter: T) -> Self {
283 Self(iter.into_iter().collect())
284 }
285}
286
287impl From<Vec<Field>> for Fields {
288 fn from(value: Vec<Field>) -> Self {
289 value.into_iter().collect()
290 }
291}
292
293impl From<Vec<FieldRef>> for Fields {
294 fn from(value: Vec<FieldRef>) -> Self {
295 Self(value.into())
296 }
297}
298
299impl From<&[FieldRef]> for Fields {
300 fn from(value: &[FieldRef]) -> Self {
301 Self(value.into())
302 }
303}
304
305impl<const N: usize> From<[FieldRef; N]> for Fields {
306 fn from(value: [FieldRef; N]) -> Self {
307 Self(Arc::new(value))
308 }
309}
310
311impl Deref for Fields {
312 type Target = [FieldRef];
313
314 fn deref(&self) -> &Self::Target {
315 self.0.as_ref()
316 }
317}
318
319impl<'a> IntoIterator for &'a Fields {
320 type Item = &'a FieldRef;
321 type IntoIter = std::slice::Iter<'a, FieldRef>;
322
323 fn into_iter(self) -> Self::IntoIter {
324 self.0.iter()
325 }
326}
327
328#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
335#[cfg_attr(feature = "serde", derive(serde::Serialize))]
336#[cfg_attr(feature = "serde", serde(transparent))]
337pub struct UnionFields(Arc<[(i8, FieldRef)]>);
338
339#[cfg(feature = "serde")]
341impl<'de> serde::Deserialize<'de> for UnionFields {
342 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
343 where
344 D: serde::Deserializer<'de>,
345 {
346 let entries = Vec::<(i8, FieldRef)>::deserialize(deserializer)?;
347 let (type_ids, fields): (Vec<i8>, Vec<FieldRef>) = entries.into_iter().unzip();
348 Self::try_new(type_ids, fields).map_err(serde::de::Error::custom)
349 }
350}
351
352impl std::fmt::Debug for UnionFields {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 self.0.as_ref().fmt(f)
355 }
356}
357
358impl std::ops::Index<usize> for UnionFields {
367 type Output = (i8, FieldRef);
368
369 fn index(&self, index: usize) -> &Self::Output {
370 &self.0[index]
371 }
372}
373
374impl UnionFields {
375 pub fn empty() -> Self {
377 Self(Arc::from([]))
378 }
379
380 pub fn try_new<F, T>(type_ids: T, fields: F) -> Result<Self, ArrowError>
418 where
419 F: IntoIterator,
420 F::Item: Into<FieldRef>,
421 T: IntoIterator<Item = i8>,
422 {
423 let mut type_ids_iter = type_ids.into_iter();
424 let mut fields_iter = fields.into_iter().map(Into::into);
425
426 let mut seen_type_ids = 0u128;
427
428 let mut out = Vec::new();
429
430 loop {
431 match (type_ids_iter.next(), fields_iter.next()) {
432 (None, None) => return Ok(Self(out.into())),
433 (Some(type_id), Some(field)) => {
434 if type_id < 0 {
436 return Err(ArrowError::InvalidArgumentError(format!(
437 "type ids must be non-negative: {type_id}"
438 )));
439 }
440
441 let mask = 1_u128 << type_id;
443 if (seen_type_ids & mask) != 0 {
444 return Err(ArrowError::InvalidArgumentError(format!(
445 "duplicate type id: {type_id}"
446 )));
447 }
448
449 seen_type_ids |= mask;
450
451 out.push((type_id, field));
452 }
453 (None, Some(_)) => {
454 return Err(ArrowError::InvalidArgumentError(
455 "fields iterator has more elements than type_ids iterator".to_string(),
456 ));
457 }
458 (Some(_), None) => {
459 return Err(ArrowError::InvalidArgumentError(
460 "type_ids iterator has more elements than fields iterator".to_string(),
461 ));
462 }
463 }
464 }
465 }
466
467 pub fn from_fields<F>(fields: F) -> Self
495 where
496 F: IntoIterator,
497 F::Item: Into<FieldRef>,
498 {
499 fields
500 .into_iter()
501 .enumerate()
502 .map(|(i, field)| {
503 let id = i8::try_from(i).expect("UnionFields cannot contain more than 128 fields");
504
505 (id, field.into())
506 })
507 .collect()
508 }
509
510 pub fn try_from_fields<F>(fields: F) -> Result<Self, ArrowError>
545 where
546 F: IntoIterator,
547 F::Item: Into<FieldRef>,
548 {
549 let mut out = Vec::with_capacity(i8::MAX as usize + 1);
550
551 for (i, field) in fields.into_iter().enumerate() {
552 let id = i8::try_from(i).map_err(|_| {
553 ArrowError::InvalidArgumentError(
554 "UnionFields cannot contain more than 128 fields".into(),
555 )
556 })?;
557
558 out.push((id, field.into()));
559 }
560
561 Ok(Self(out.into()))
562 }
563
564 pub fn size(&self) -> usize {
566 self.iter()
567 .map(|(_, field)| field.size() + std::mem::size_of::<(i8, FieldRef)>())
568 .sum()
569 }
570
571 pub fn len(&self) -> usize {
573 self.0.len()
574 }
575
576 pub fn is_empty(&self) -> bool {
578 self.0.is_empty()
579 }
580
581 pub fn iter(&self) -> impl Iterator<Item = (i8, &FieldRef)> + '_ {
583 self.0.iter().map(|(id, f)| (*id, f))
584 }
585
586 pub fn get(&self, index: usize) -> Option<&(i8, FieldRef)> {
608 self.0.get(index)
609 }
610
611 pub fn find_by_type_id(&self, type_id: i8) -> Option<(i8, &FieldRef)> {
614 self.iter().find(|&(i, _)| i == type_id)
615 }
616
617 pub fn find_by_field(&self, field: &Field) -> Option<(i8, &FieldRef)> {
620 self.iter().find(|&(_, f)| f.as_ref() == field)
621 }
622
623 pub(crate) fn try_merge(&mut self, other: &Self) -> Result<(), ArrowError> {
627 let mut output: Vec<_> = self.iter().map(|(id, f)| (id, f.clone())).collect();
629 for (field_type_id, from_field) in other.iter() {
630 let mut is_new_field = true;
631 for (self_type_id, self_field) in &mut output {
632 if from_field == self_field {
633 if *self_type_id != field_type_id {
636 return Err(ArrowError::SchemaError(format!(
637 "Fail to merge schema field '{}' because the self_type_id = {} does not equal field_type_id = {}",
638 self_field.name(),
639 self_type_id,
640 field_type_id
641 )));
642 }
643
644 is_new_field = false;
645 break;
646 }
647 }
648
649 if is_new_field {
650 output.push((field_type_id, from_field.clone()))
651 }
652 }
653 let (type_ids, fields): (Vec<i8>, Vec<FieldRef>) = output.into_iter().unzip();
656 *self = Self::try_new(type_ids, fields)?;
657 Ok(())
658 }
659}
660
661impl FromIterator<(i8, FieldRef)> for UnionFields {
662 fn from_iter<T: IntoIterator<Item = (i8, FieldRef)>>(iter: T) -> Self {
670 let iter = iter.into_iter();
671 let (type_ids, fields): (Vec<i8>, Vec<FieldRef>) = iter.unzip();
672 Self::try_new(type_ids, fields).expect("invalid arguments passed")
673 }
674}
675
676#[cfg(test)]
677mod tests {
678 use super::*;
679 use crate::UnionMode;
680
681 #[test]
682 fn test_filter() {
683 let floats = Fields::from(vec![
684 Field::new("a", DataType::Float32, false),
685 Field::new("b", DataType::Float32, false),
686 ]);
687 let fields = Fields::from(vec![
688 Field::new("a", DataType::Int32, true),
689 Field::new("floats", DataType::Struct(floats.clone()), true),
690 Field::new("b", DataType::Int16, true),
691 Field::new(
692 "c",
693 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
694 false,
695 ),
696 Field::new(
697 "d",
698 DataType::Dictionary(
699 Box::new(DataType::Int32),
700 Box::new(DataType::Struct(floats.clone())),
701 ),
702 false,
703 ),
704 Field::new_list(
705 "e",
706 Field::new("floats", DataType::Struct(floats.clone()), true),
707 true,
708 ),
709 Field::new_fixed_size_list(
710 "f",
711 Field::new_list_field(DataType::Int32, false),
712 3,
713 false,
714 ),
715 Field::new_map(
716 "g",
717 Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
718 Field::new(
719 Field::MAP_KEY_FIELD_DEFAULT_NAME,
720 DataType::LargeUtf8,
721 false,
722 ),
723 Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, true),
724 false,
725 false,
726 ),
727 Field::new(
728 "h",
729 DataType::Union(
730 UnionFields::try_new(
731 vec![1, 3],
732 vec![
733 Field::new("field1", DataType::UInt8, false),
734 Field::new("field3", DataType::Utf8, false),
735 ],
736 )
737 .unwrap(),
738 UnionMode::Dense,
739 ),
740 true,
741 ),
742 Field::new(
743 "i",
744 DataType::RunEndEncoded(
745 Arc::new(Field::new(
746 Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME,
747 DataType::Int32,
748 false,
749 )),
750 Arc::new(Field::new(
751 Field::REE_VALUES_FIELD_DEFAULT_NAME,
752 DataType::Struct(floats.clone()),
753 true,
754 )),
755 ),
756 false,
757 ),
758 ]);
759
760 let floats_a = DataType::Struct(vec![floats[0].clone()].into());
761
762 let r = fields.filter_leaves(|idx, _| idx == 0 || idx == 1);
763 assert_eq!(r.len(), 2);
764 assert_eq!(r[0], fields[0]);
765 assert_eq!(r[1].data_type(), &floats_a);
766
767 let r = fields.filter_leaves(|_, f| f.name() == "a");
768 assert_eq!(r.len(), 5);
769 assert_eq!(r[0], fields[0]);
770 assert_eq!(r[1].data_type(), &floats_a);
771 assert_eq!(
772 r[2].data_type(),
773 &DataType::Dictionary(Box::new(DataType::Int32), Box::new(floats_a.clone()))
774 );
775 assert_eq!(
776 r[3].as_ref(),
777 &Field::new_list("e", Field::new("floats", floats_a.clone(), true), true)
778 );
779 assert_eq!(
780 r[4].as_ref(),
781 &Field::new(
782 "i",
783 DataType::RunEndEncoded(
784 Arc::new(Field::new(
785 Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME,
786 DataType::Int32,
787 false
788 )),
789 Arc::new(Field::new(
790 Field::REE_VALUES_FIELD_DEFAULT_NAME,
791 floats_a.clone(),
792 true
793 )),
794 ),
795 false,
796 )
797 );
798
799 let r = fields.filter_leaves(|_, f| f.name() == "floats");
800 assert_eq!(r.len(), 0);
801
802 let r = fields.filter_leaves(|idx, _| idx == 9);
803 assert_eq!(r.len(), 1);
804 assert_eq!(r[0], fields[6]);
805
806 let r = fields.filter_leaves(|idx, _| idx == 10 || idx == 11);
807 assert_eq!(r.len(), 1);
808 assert_eq!(r[0], fields[7]);
809
810 let union = DataType::Union(
811 UnionFields::try_new(vec![1], vec![Field::new("field1", DataType::UInt8, false)])
812 .unwrap(),
813 UnionMode::Dense,
814 );
815
816 let r = fields.filter_leaves(|idx, _| idx == 12);
817 assert_eq!(r.len(), 1);
818 assert_eq!(r[0].data_type(), &union);
819
820 let r = fields.filter_leaves(|idx, _| idx == 14 || idx == 15);
821 assert_eq!(r.len(), 1);
822 assert_eq!(r[0], fields[9]);
823
824 let r = fields.try_filter_leaves(|_, _| Err(ArrowError::SchemaError("error".to_string())));
826 assert!(r.is_err());
827 }
828
829 #[test]
830 fn test_filter_list_view() {
831 let floats = Fields::from(vec![
832 Field::new("a", DataType::Float32, false),
833 Field::new("b", DataType::Float32, false),
834 ]);
835 let fields = Fields::from(vec![
836 Field::new(
837 "lv_struct",
838 DataType::ListView(Arc::new(Field::new(
839 "floats",
840 DataType::Struct(floats.clone()),
841 true,
842 ))),
843 true,
844 ),
845 Field::new(
846 "llv_struct",
847 DataType::LargeListView(Arc::new(Field::new(
848 "floats",
849 DataType::Struct(floats.clone()),
850 true,
851 ))),
852 false,
853 ),
854 Field::new(
855 "lv_prim",
856 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int32, false))),
857 true,
858 ),
859 Field::new(
860 "llv_prim",
861 DataType::LargeListView(Arc::new(Field::new_list_field(DataType::Int64, true))),
862 false,
863 ),
864 ]);
865
866 let floats_a = DataType::Struct(vec![floats[0].clone()].into());
867
868 let r = fields.filter_leaves(|_, f| f.name() == "a");
870 assert_eq!(r.len(), 2);
871 assert_eq!(
872 r[0].as_ref(),
873 &Field::new(
874 "lv_struct",
875 DataType::ListView(Arc::new(Field::new("floats", floats_a.clone(), true))),
876 true,
877 )
878 );
879 assert_eq!(
880 r[1].as_ref(),
881 &Field::new(
882 "llv_struct",
883 DataType::LargeListView(Arc::new(Field::new("floats", floats_a, true))),
884 false,
885 )
886 );
887
888 let r = fields.filter_leaves(|_, f| f.name() == "lv_struct" || f.name() == "llv_struct");
890 assert_eq!(r.len(), 0);
891
892 let r = fields.filter_leaves(|idx, _| idx == 4 || idx == 5);
894 assert_eq!(r.len(), 2);
895 assert_eq!(r[0], fields[2]);
896 assert_eq!(r[1], fields[3]);
897 }
898
899 #[test]
900 fn test_union_fields_try_new_valid() {
901 let res = UnionFields::try_new(
902 vec![1, 6, 7],
903 vec![
904 Field::new("f1", DataType::UInt8, false),
905 Field::new("f6", DataType::Utf8, false),
906 Field::new("f7", DataType::Int32, true),
907 ],
908 );
909 assert!(res.is_ok());
910 let union_fields = res.unwrap();
911 assert_eq!(union_fields.len(), 3);
912 assert_eq!(
913 union_fields.iter().map(|(id, _)| id).collect::<Vec<_>>(),
914 vec![1, 6, 7]
915 );
916 }
917
918 #[test]
919 fn test_union_fields_try_new_empty() {
920 let res = UnionFields::try_new(Vec::<i8>::new(), Vec::<Field>::new());
921 assert!(res.is_ok());
922 assert!(res.unwrap().is_empty());
923 }
924
925 #[test]
926 fn test_union_fields_try_new_duplicate_type_id() {
927 let res = UnionFields::try_new(
928 vec![1, 1],
929 vec![
930 Field::new("f1", DataType::UInt8, false),
931 Field::new("f2", DataType::Utf8, false),
932 ],
933 );
934 assert!(res.is_err());
935 assert!(
936 res.unwrap_err()
937 .to_string()
938 .contains("duplicate type id: 1")
939 );
940 }
941
942 #[test]
943 fn test_union_fields_try_new_duplicate_field() {
944 let field = Field::new("field", DataType::UInt8, false);
945 let res = UnionFields::try_new(vec![1, 2], vec![field.clone(), field]);
946 assert!(res.is_ok());
947 }
948
949 #[test]
950 fn test_union_fields_try_new_more_type_ids() {
951 let res = UnionFields::try_new(
952 vec![1, 2, 3],
953 vec![
954 Field::new("f1", DataType::UInt8, false),
955 Field::new("f2", DataType::Utf8, false),
956 ],
957 );
958 assert!(res.is_err());
959 assert!(
960 res.unwrap_err()
961 .to_string()
962 .contains("type_ids iterator has more elements")
963 );
964 }
965
966 #[test]
967 fn test_union_fields_try_new_more_fields() {
968 let res = UnionFields::try_new(
969 vec![1, 2],
970 vec![
971 Field::new("f1", DataType::UInt8, false),
972 Field::new("f2", DataType::Utf8, false),
973 Field::new("f3", DataType::Int32, true),
974 ],
975 );
976 assert!(res.is_err());
977 assert!(
978 res.unwrap_err()
979 .to_string()
980 .contains("fields iterator has more elements")
981 );
982 }
983
984 #[test]
985 fn test_union_fields_try_new_negative_type_ids() {
986 let res = UnionFields::try_new(
987 vec![-128, -1, 0, 127],
988 vec![
989 Field::new("field_min", DataType::UInt8, false),
990 Field::new("field_neg", DataType::Utf8, false),
991 Field::new("field_zero", DataType::Int32, true),
992 Field::new("field_max", DataType::Boolean, false),
993 ],
994 );
995 assert!(res.is_err());
996 assert!(
997 res.unwrap_err()
998 .to_string()
999 .contains("type ids must be non-negative")
1000 )
1001 }
1002
1003 #[test]
1004 fn test_union_fields_try_new_complex_types() {
1005 let res = UnionFields::try_new(
1006 vec![0, 1, 2],
1007 vec![
1008 Field::new(
1009 "struct_field",
1010 DataType::Struct(Fields::from(vec![
1011 Field::new("a", DataType::Int32, false),
1012 Field::new("b", DataType::Utf8, true),
1013 ])),
1014 false,
1015 ),
1016 Field::new_list(
1017 "list_field",
1018 Field::new("item", DataType::Float64, true),
1019 true,
1020 ),
1021 Field::new(
1022 "dict_field",
1023 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1024 false,
1025 ),
1026 ],
1027 );
1028 assert!(res.is_ok());
1029 assert_eq!(res.unwrap().len(), 3);
1030 }
1031
1032 #[test]
1033 fn test_union_fields_try_new_single_field() {
1034 let res = UnionFields::try_new(
1035 vec![42],
1036 vec![Field::new("only_field", DataType::Int64, false)],
1037 );
1038 assert!(res.is_ok());
1039 let union_fields = res.unwrap();
1040 assert_eq!(union_fields.len(), 1);
1041 assert_eq!(union_fields.iter().next().unwrap().0, 42);
1042 }
1043
1044 #[test]
1045 fn test_union_fields_try_from_fields_empty() {
1046 let res = UnionFields::try_from_fields(Vec::<Field>::new());
1047 assert!(res.is_ok());
1048 assert!(res.unwrap().is_empty());
1049 }
1050
1051 #[test]
1052 fn test_union_fields_try_from_fields_single() {
1053 let res = UnionFields::try_from_fields(vec![Field::new("only", DataType::Int64, false)]);
1054 assert!(res.is_ok());
1055 let union_fields = res.unwrap();
1056 assert_eq!(union_fields.len(), 1);
1057 assert_eq!(union_fields.iter().next().unwrap().0, 0);
1058 }
1059
1060 #[test]
1061 fn test_union_fields_try_from_fields_too_many() {
1062 let many_fields: Vec<_> = (0..200)
1063 .map(|i| Field::new(format!("field{i}"), DataType::Int32, false))
1064 .collect();
1065 let res = UnionFields::try_from_fields(many_fields);
1066 assert!(res.is_err());
1067 assert!(
1068 res.unwrap_err()
1069 .to_string()
1070 .contains("UnionFields cannot contain more than 128 fields")
1071 );
1072 }
1073
1074 #[test]
1075 fn test_union_fields_try_from_fields_max_valid() {
1076 let fields: Vec<_> = (0..=i8::MAX)
1077 .map(|i| Field::new(format!("field{i}"), DataType::Int32, false))
1078 .collect();
1079 let res = UnionFields::try_from_fields(fields);
1080 assert!(res.is_ok());
1081 let union_fields = res.unwrap();
1082 assert_eq!(union_fields.len(), 128);
1083 assert_eq!(union_fields.iter().map(|(id, _)| id).min().unwrap(), 0);
1084 assert_eq!(union_fields.iter().map(|(id, _)| id).max().unwrap(), 127);
1085 }
1086
1087 #[test]
1088 fn test_union_fields_try_from_fields_over_max() {
1089 let fields: Vec<_> = (0..129)
1091 .map(|i| Field::new(format!("field{i}"), DataType::Int32, false))
1092 .collect();
1093 let res = UnionFields::try_from_fields(fields);
1094 assert!(res.is_err());
1095 }
1096
1097 #[test]
1098 fn test_union_fields_try_from_fields_complex_types() {
1099 let res = UnionFields::try_from_fields(vec![
1100 Field::new(
1101 "struct_field",
1102 DataType::Struct(Fields::from(vec![
1103 Field::new("a", DataType::Int32, false),
1104 Field::new("b", DataType::Utf8, true),
1105 ])),
1106 false,
1107 ),
1108 Field::new_list(
1109 "list_field",
1110 Field::new("item", DataType::Float64, true),
1111 true,
1112 ),
1113 Field::new(
1114 "dict_field",
1115 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1116 false,
1117 ),
1118 ]);
1119 assert!(res.is_ok());
1120 assert_eq!(res.unwrap().len(), 3);
1121 }
1122
1123 #[test]
1124 #[should_panic(
1125 expected = "invalid arguments passed: InvalidArgumentError(\"type ids must be non-negative: -1\")"
1126 )]
1127 fn test_union_fields_from_iter_should_validate() {
1128 let fields: Vec<(i8, FieldRef)> = vec![
1129 (0, Arc::new(Field::new("a", DataType::Int32, true))),
1130 (-1, Arc::new(Field::new("a", DataType::Int32, true))),
1131 ];
1132 UnionFields::from_iter(fields);
1133 }
1134
1135 #[cfg(feature = "serde")]
1136 #[test]
1137 fn test_union_fields_serde_round_trip() {
1138 let fields = UnionFields::try_new(
1139 vec![1, 3],
1140 vec![
1141 Field::new("a", DataType::Int32, true),
1142 Field::new("b", DataType::Utf8, true),
1143 ],
1144 )
1145 .unwrap();
1146 let serialized = postcard::to_stdvec(&fields).unwrap();
1147 let deserialized: UnionFields = postcard::from_bytes(&serialized).unwrap();
1148 assert_eq!(fields, deserialized);
1149 }
1150
1151 #[cfg(feature = "serde")]
1152 #[test]
1153 fn test_union_fields_deserialize_should_validate() {
1154 let field = Arc::new(Field::new("a", DataType::Int32, true));
1155
1156 let duplicate: Vec<(i8, FieldRef)> = vec![(1, Arc::clone(&field)), (1, Arc::clone(&field))];
1157 let serialized = serde_json::to_string(&duplicate).unwrap();
1158 let err = serde_json::from_str::<UnionFields>(&serialized).unwrap_err();
1159 assert!(err.to_string().contains("duplicate type id: 1"), "{err}");
1160
1161 let negative: Vec<(i8, FieldRef)> = vec![(0, Arc::clone(&field)), (-1, field)];
1162 let serialized = serde_json::to_string(&negative).unwrap();
1163 let err = serde_json::from_str::<UnionFields>(&serialized).unwrap_err();
1164 assert!(
1165 err.to_string()
1166 .contains("type ids must be non-negative: -1"),
1167 "{err}"
1168 );
1169 }
1170}