fn coerce_data_type<A: Borrow<DataType>>(datatypes: &[A]) -> DataType {
    use DataType::*;

    let are_all_equal = datatypes.windows(2).all(|w| w[0].borrow() == w[1].borrow());

    if are_all_equal {
        return datatypes[0].borrow().clone();
    }

    let are_all_structs = datatypes.iter().all(|x| matches!(x.borrow(), Struct(_)));

    if are_all_structs {
        // all are structs => union of all fields (that may have equal names)
        let fields = datatypes.iter().fold(vec![], |mut acc, dt| {
            if let Struct(new_fields) = dt.borrow() {
                acc.extend(new_fields);
            };
            acc
        });
        // group fields by unique
        let fields = fields.iter().fold(
            HashMap::<&String, Vec<&DataType>>::new(),
            |mut acc, field| {
                match acc.entry(&field.name) {
                    indexmap::map::Entry::Occupied(mut v) => {
                        v.get_mut().push(&field.data_type);
                    }
                    indexmap::map::Entry::Vacant(v) => {
                        v.insert(vec![&field.data_type]);
                    }
                }
                acc
            },
        );
        // and finally, coerce each of the fields within the same name
        let fields = fields
            .into_iter()
            .map(|(name, dts)| Field::new(name, coerce_data_type(&dts), true))
            .collect();
        return Struct(fields);
    } else if datatypes.len() > 2 {
        return Utf8;
    }
    let (lhs, rhs) = (datatypes[0].borrow(), datatypes[1].borrow());

    return match (lhs, rhs) {
        (lhs, rhs) if lhs == rhs => lhs.clone(),
        (List(lhs), List(rhs)) => {
            let inner = coerce_data_type(&[lhs.data_type(), rhs.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (scalar, List(list)) => {
            let inner = coerce_data_type(&[scalar, list.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (List(list), scalar) => {
            let inner = coerce_data_type(&[scalar, list.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (Float64, Int64) => Float64,
        (Int64, Float64) => Float64,
        (Int64, Boolean) => Int64,
        (Boolean, Int64) => Int64,
        (_, _) => Utf8,
    };
}
/// Coerce an heterogeneous set of [`DataType`] into a single one. Rules:
/// * `Int64` and `Float64` are `Float64`
/// * Lists and scalars are coerced to a list of a compatible scalar
/// * Structs contain the union of all fields
/// * All other types are coerced to `Utf8`
Coerce an heterogeneous set of [`DataType`] into a single one.
Coerce an heterogeneous set of [ ` DataType ` ] into a single one .
fn coerce_data_type<A: Borrow<DataType>>(datatypes: &[A]) -> DataType {
    use DataType::*;
    let are_all_equal = datatypes.windows(2).all(|w| w[0].borrow() == w[1].borrow());
    if are_all_equal {
        return datatypes[0].borrow().clone();
    }
    let are_all_structs = datatypes.iter().all(|x| matches!(x.borrow(), Struct(_)));
    if are_all_structs {
        // all are structs => union of all fields (that may have equal names)
        let fields = datatypes.iter().fold(vec![], |mut acc, dt| {
            if let Struct(new_fields) = dt.borrow() {
                acc.extend(new_fields);
            };
            acc
        });
        // group fields by unique
        let fields = fields.iter().fold(
            HashMap::<&String, Vec<&DataType>>::new(),
            |mut acc, field| {
                match acc.entry(&field.name) {
                    indexmap::map::Entry::Occupied(mut v) => {
                        v.get_mut().push(&field.data_type);
                    }
                    indexmap::map::Entry::Vacant(v) => {
                        v.insert(vec![&field.data_type]);
                    }
                }
                acc
            },
        );
        // and finally, coerce each of the fields within the same name
        let fields = fields
            .into_iter()
            .map(|(name, dts)| Field::new(name, coerce_data_type(&dts), true))
            .collect();
        return Struct(fields);
    } else if datatypes.len() > 2 {
        return Utf8;
    }
    let (lhs, rhs) = (datatypes[0].borrow(), datatypes[1].borrow());
    return match (lhs, rhs) {
        (lhs, rhs) if lhs == rhs => lhs.clone(),
        (List(lhs), List(rhs)) => {
            let inner = coerce_data_type(&[lhs.data_type(), rhs.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (scalar, List(list)) => {
            let inner = coerce_data_type(&[scalar, list.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (List(list), scalar) => {
            let inner = coerce_data_type(&[scalar, list.data_type()]);
            List(Box::new(Field::new(ITEM_NAME, inner, true)))
        }
        (Float64, Int64) => Float64,
        (Int64, Float64) => Float64,
        (Int64, Boolean) => Int64,
        (Boolean, Int64) => Int64,
        (_, _) => Utf8,
    };
}
fn coerce_data_type < A : Borrow < DataType > > ( datatypes : & [ A ] ) -> DataType { use DataType :: * ; let are_all_equal = datatypes . windows ( 2 ) . all ( | w | w [ 0 ] . borrow ( ) == w [ 1 ] . borrow ( ) ) ; if are_all_equal { return datatypes [ 0 ] . borrow ( ) . clone ( ) ; } let are_all_structs = datatypes . iter ( ) . all ( | x | matches ! ( x borrow ( ) Struct ( ) ) ) ; if are_all_structs { // all are structs => union of all fields (that may have equal names) let fields = datatypes . iter ( ) . fold ( vec ! [ ] , | mut acc , dt | { if let Struct ( new_fields ) = dt . borrow ( ) { acc . extend ( new_fields ) ; } ; acc } ) ; // group fields by unique let fields = fields . iter ( ) . fold ( HashMap :: < & String , Vec < & DataType > > :: new ( ) , | mut acc , field | { match acc . entry ( & field . name ) { indexmap :: map :: Entry :: Occupied ( mut v ) => { v . get_mut ( ) . push ( & field . data_type ) ; } indexmap :: map :: Entry :: Vacant ( v ) => { v . insert ( vec ! [ field data_type ] ) ; } } acc } , ) ; // and finally, coerce each of the fields within the same name let fields = fields . into_iter ( ) . map ( | ( name , dts ) | Field :: new ( name , coerce_data_type ( & dts ) , true ) ) . collect ( ) ; return Struct ( fields ) ; } else if datatypes . len ( ) > 2 { return Utf8 ; } let ( lhs , rhs ) = ( datatypes [ 0 ] . borrow ( ) , datatypes [ 1 ] . borrow ( ) ) ; return match ( lhs , rhs ) { ( lhs , rhs ) if lhs == rhs => lhs . clone ( ) , ( List ( lhs ) , List ( rhs ) ) => { let inner = coerce_data_type ( & [ lhs . data_type ( ) , rhs . data_type ( ) ] ) ; List ( Box :: new ( Field :: new ( ITEM_NAME , inner , true ) ) ) } ( scalar , List ( list ) ) => { let inner = coerce_data_type ( & [ scalar , list . data_type ( ) ] ) ; List ( Box :: new ( Field :: new ( ITEM_NAME , inner , true ) ) ) } ( List ( list ) , scalar ) => { let inner = coerce_data_type ( & [ scalar , list . data_type ( ) ] ) ; List ( Box :: new ( Field :: new ( ITEM_NAME , inner , true ) ) ) } ( Float64 , Int64 ) => Float64 , ( Int64 , Float64 ) => Float64 , ( Int64 , Boolean ) => Int64 , ( Boolean , Int64 ) => Int64 , ( _ , _ ) => Utf8 , } ; }
Coerce an heterogeneous set of [`DataType`] into a single one.
Coerce an heterogeneous set of [ ` DataType ` ] into a single one .
datatypes
&[A]
datatypes
&[A]