Skip to main content

arrow_schema/
fields.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::ops::Deref;
19use std::sync::Arc;
20
21use crate::{ArrowError, DataType, Field, FieldRef};
22
23/// A cheaply cloneable, owned slice of [`FieldRef`]
24///
25/// Similar to `Arc<Vec<FieldRef>>` or `Arc<[FieldRef]>`
26///
27/// Can be constructed in a number of ways
28///
29/// ```
30/// # use std::sync::Arc;
31/// # use arrow_schema::{DataType, Field, Fields, SchemaBuilder};
32/// // Can be constructed from Vec<Field>
33/// Fields::from(vec![Field::new("a", DataType::Boolean, false)]);
34/// // Can be constructed from Vec<FieldRef>
35/// Fields::from(vec![Arc::new(Field::new("a", DataType::Boolean, false))]);
36/// // Can be constructed from an iterator of Field
37/// std::iter::once(Field::new("a", DataType::Boolean, false)).collect::<Fields>();
38/// // Can be constructed from an iterator of FieldRef
39/// std::iter::once(Arc::new(Field::new("a", DataType::Boolean, false))).collect::<Fields>();
40/// ```
41///
42/// See [`SchemaBuilder`] for mutating or updating [`Fields`]
43///
44/// ```
45/// # use arrow_schema::{DataType, Field, SchemaBuilder};
46/// let mut builder = SchemaBuilder::new();
47/// builder.push(Field::new("a", DataType::Boolean, false));
48/// builder.push(Field::new("b", DataType::Boolean, false));
49/// let fields = builder.finish().fields;
50///
51/// let mut builder = SchemaBuilder::from(&fields);
52/// builder.remove(0);
53/// let new = builder.finish().fields;
54/// ```
55///
56/// [`SchemaBuilder`]: crate::SchemaBuilder
57#[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    /// Returns a new empty [`Fields`]
70    pub fn empty() -> Self {
71        Self(Arc::new([]))
72    }
73
74    /// Return size of this instance in bytes.
75    pub fn size(&self) -> usize {
76        self.iter()
77            .map(|field| field.size() + std::mem::size_of::<FieldRef>())
78            .sum()
79    }
80
81    /// Searches for a field by name, returning it along with its index if found
82    pub fn find(&self, name: &str) -> Option<(usize, &FieldRef)> {
83        self.0.iter().enumerate().find(|(_, b)| b.name() == name)
84    }
85
86    /// Check to see if `self` is a superset of `other`
87    ///
88    /// In particular returns true if both have the same number of fields, and [`Field::contains`]
89    /// for each field across self and other
90    ///
91    /// In other words, any record that conforms to `other` should also conform to `self`
92    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    /// Returns a copy of this [`Fields`] containing only those [`FieldRef`] passing a predicate
104    ///
105    /// Performs a depth-first scan of [`Fields`] invoking `filter` for each [`FieldRef`]
106    /// containing no child [`FieldRef`], a leaf field, along with a count of the number
107    /// of such leaves encountered so far. Only [`FieldRef`] for which `filter`
108    /// returned `true` will be included in the result.
109    ///
110    /// This can therefore be used to select a subset of fields from nested types
111    /// such as [`DataType::Struct`] or [`DataType::List`].
112    ///
113    /// ```
114    /// # use arrow_schema::{DataType, Field, Fields};
115    /// let fields = Fields::from(vec![
116    ///     Field::new("a", DataType::Int32, true), // Leaf 0
117    ///     Field::new("b", DataType::Struct(Fields::from(vec![
118    ///         Field::new("c", DataType::Float32, false), // Leaf 1
119    ///         Field::new("d", DataType::Float64, false), // Leaf 2
120    ///         Field::new("e", DataType::Struct(Fields::from(vec![
121    ///             Field::new("f", DataType::Int32, false),   // Leaf 3
122    ///             Field::new("g", DataType::Float16, false), // Leaf 4
123    ///         ])), true),
124    ///     ])), false)
125    /// ]);
126    /// let filtered = fields.filter_leaves(|idx, _| [0, 2, 3, 4].contains(&idx));
127    /// let expected = Fields::from(vec![
128    ///     Field::new("a", DataType::Int32, true),
129    ///     Field::new("b", DataType::Struct(Fields::from(vec![
130    ///         Field::new("d", DataType::Float64, false),
131    ///         Field::new("e", DataType::Struct(Fields::from(vec![
132    ///             Field::new("f", DataType::Int32, false),
133    ///             Field::new("g", DataType::Float16, false),
134    ///         ])), true),
135    ///     ])), false)
136    /// ]);
137    /// assert_eq!(filtered, expected);
138    /// ```
139    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    /// Returns a copy of this [`Fields`] containing only those [`FieldRef`] passing a predicate
145    /// or an error if the predicate fails.
146    ///
147    /// See [`Fields::filter_leaves`] for more information.
148    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(),       // Key must be integer
160                RunEndEncoded(_, v) => v.data_type(), // Run-ends must be integer
161                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/// A cheaply cloneable, owned collection of [`FieldRef`] and their corresponding
329/// type ids.
330///
331/// Invariants:
332/// - All type ids are unique
333/// - All type ids are non-negative
334#[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// Manual implementation to enforce invariants per docstring above
340#[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
358/// Allows direct indexing into [`UnionFields`] to access fields by position.
359///
360/// # Panics
361///
362/// Panics if the index is out of bounds. Note that [`UnionFields`] supports
363/// a maximum of 128 fields, as type IDs are represented as `i8` values.
364///
365/// For a non-panicking alternative, use [`UnionFields::get`].
366impl 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    /// Create a new [`UnionFields`] with no fields
376    pub fn empty() -> Self {
377        Self(Arc::from([]))
378    }
379
380    /// Create a new [`UnionFields`] from a [`Fields`] and array of type_ids
381    ///
382    /// See <https://arrow.apache.org/docs/format/Columnar.html#union-layout>
383    ///
384    /// # Errors
385    ///
386    /// This function returns an error if:
387    /// - Iterators are not the same length
388    /// - Any type_id appears more than once (duplicate type ids)
389    /// - There is a negative type_id
390    ///
391    /// # Examples
392    ///
393    /// ```
394    /// use arrow_schema::{DataType, Field, UnionFields};
395    /// // Create a new UnionFields with type id mapping
396    /// // 1 -> DataType::UInt8
397    /// // 3 -> DataType::Utf8
398    /// let result = UnionFields::try_new(
399    ///     vec![1, 3],
400    ///     vec![
401    ///         Field::new("field1", DataType::UInt8, false),
402    ///         Field::new("field3", DataType::Utf8, false),
403    ///     ],
404    /// );
405    /// assert!(result.is_ok());
406    ///
407    /// // This will fail due to duplicate type ids
408    /// let result = UnionFields::try_new(
409    ///     vec![1, 1],
410    ///     vec![
411    ///         Field::new("field1", DataType::UInt8, false),
412    ///         Field::new("field2", DataType::Utf8, false),
413    ///     ],
414    /// );
415    /// assert!(result.is_err());
416    /// ```
417    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                    // check type id is non-negative
435                    if type_id < 0 {
436                        return Err(ArrowError::InvalidArgumentError(format!(
437                            "type ids must be non-negative: {type_id}"
438                        )));
439                    }
440
441                    // check type id uniqueness
442                    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    /// Create a new [`UnionFields`] from a collection of fields with automatically
468    /// assigned type IDs starting from 0.
469    ///
470    /// The type IDs are assigned in increasing order: 0, 1, 2, 3, etc.
471    ///
472    /// See <https://arrow.apache.org/docs/format/Columnar.html#union-layout>
473    ///
474    /// # Panics
475    ///
476    /// Panics if the number of fields exceeds 127 (the maximum value for i8 type IDs).
477    ///
478    /// If you want to avoid panics, use [`UnionFields::try_from_fields`] instead, which
479    /// returns a `Result`.
480    ///
481    /// # Examples
482    ///
483    /// ```
484    /// use arrow_schema::{DataType, Field, UnionFields};
485    /// // Create a new UnionFields with automatic type id assignment
486    /// // 0 -> DataType::UInt8
487    /// // 1 -> DataType::Utf8
488    /// let union_fields = UnionFields::from_fields(vec![
489    ///     Field::new("field1", DataType::UInt8, false),
490    ///     Field::new("field2", DataType::Utf8, false),
491    /// ]);
492    /// assert_eq!(union_fields.len(), 2);
493    /// ```
494    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    /// Create a new [`UnionFields`] from a collection of fields with automatically
511    /// assigned type IDs starting from 0.
512    ///
513    /// The type IDs are assigned in increasing order: 0, 1, 2, 3, etc.
514    ///
515    /// This is the non-panicking version of [`UnionFields::from_fields`].
516    ///
517    /// See <https://arrow.apache.org/docs/format/Columnar.html#union-layout>
518    ///
519    /// # Errors
520    ///
521    /// Returns an error if the number of fields exceeds 127 (the maximum value for i8 type IDs).
522    ///
523    /// # Examples
524    ///
525    /// ```
526    /// use arrow_schema::{DataType, Field, UnionFields};
527    /// // Create a new UnionFields with automatic type id assignment
528    /// // 0 -> DataType::UInt8
529    /// // 1 -> DataType::Utf8
530    /// let result = UnionFields::try_from_fields(vec![
531    ///     Field::new("field1", DataType::UInt8, false),
532    ///     Field::new("field2", DataType::Utf8, false),
533    /// ]);
534    /// assert!(result.is_ok());
535    /// assert_eq!(result.unwrap().len(), 2);
536    ///
537    /// // This will fail with too many fields
538    /// let many_fields: Vec<_> = (0..200)
539    ///     .map(|i| Field::new(format!("field{}", i), DataType::Int32, false))
540    ///     .collect();
541    /// let result = UnionFields::try_from_fields(many_fields);
542    /// assert!(result.is_err());
543    /// ```
544    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    /// Return size of this instance in bytes.
565    pub fn size(&self) -> usize {
566        self.iter()
567            .map(|(_, field)| field.size() + std::mem::size_of::<(i8, FieldRef)>())
568            .sum()
569    }
570
571    /// Returns the number of fields in this [`UnionFields`]
572    pub fn len(&self) -> usize {
573        self.0.len()
574    }
575
576    /// Returns `true` if this is empty
577    pub fn is_empty(&self) -> bool {
578        self.0.is_empty()
579    }
580
581    /// Returns an iterator over the fields and type ids in this [`UnionFields`]
582    pub fn iter(&self) -> impl Iterator<Item = (i8, &FieldRef)> + '_ {
583        self.0.iter().map(|(id, f)| (*id, f))
584    }
585
586    /// Returns a reference to the field at the given index, or `None` if out of bounds.
587    ///
588    /// This is a safe alternative to direct indexing via `[]`.
589    ///
590    /// # Example
591    ///
592    /// ```
593    /// use arrow_schema::{DataType, Field, UnionFields};
594    ///
595    /// let fields = UnionFields::try_new(
596    ///     vec![1, 3],
597    ///     vec![
598    ///         Field::new("field1", DataType::UInt8, false),
599    ///         Field::new("field3", DataType::Utf8, false),
600    ///     ],
601    /// ).unwrap();
602    ///
603    /// assert!(fields.get(0).is_some());
604    /// assert!(fields.get(1).is_some());
605    /// assert!(fields.get(2).is_none());
606    /// ```
607    pub fn get(&self, index: usize) -> Option<&(i8, FieldRef)> {
608        self.0.get(index)
609    }
610
611    /// Searches for a field by its type id, returning the type id and field reference if found.
612    /// Returns `None` if no field with the given type id exists.
613    pub fn find_by_type_id(&self, type_id: i8) -> Option<(i8, &FieldRef)> {
614        self.iter().find(|&(i, _)| i == type_id)
615    }
616
617    /// Searches for a field by value equality, returning its type id and reference if found.
618    /// Returns `None` if no matching field exists in this [`UnionFields`].
619    pub fn find_by_field(&self, field: &Field) -> Option<(i8, &FieldRef)> {
620        self.iter().find(|&(_, f)| f.as_ref() == field)
621    }
622
623    /// Merge this field into self if it is compatible.
624    ///
625    /// See [`Field::try_merge`]
626    pub(crate) fn try_merge(&mut self, other: &Self) -> Result<(), ArrowError> {
627        // TODO: This currently may produce duplicate type IDs (#3982)
628        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 the nested fields in two unions are the same, they must have same
634                    // type id.
635                    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        // TODO: see above comment; can we remove the need to go through try_new
654        //       and just validate in this function ourselves?
655        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    /// # Panics
663    ///
664    /// This will panic on invalid inputs:
665    /// - Duplicate type IDs
666    /// - Negative type IDs
667    ///
668    /// Prefer using [`UnionFields::try_new`] for a fallible construction method.
669    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        // Propagate error
825        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        // Filter by leaf field name "a" inside nested structs of ListView and LargeListView
869        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        // Parent ListView/LargeListView fields are not leaves themselves
889        let r = fields.filter_leaves(|_, f| f.name() == "lv_struct" || f.name() == "llv_struct");
890        assert_eq!(r.len(), 0);
891
892        // Leaf indices: 0,1 (lv_struct.floats.a,b), 2,3 (llv_struct.floats.a,b), 4 (lv_prim.item), 5 (llv_prim.item)
893        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        // 129 fields should fail
1090        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}