use itertools::Itertools;
use smallvec::SmallVec;
use super::*;
use crate::for_all_variants;
pub trait ArrayToVecExt: Array {
fn to_vec(&self) -> Vec<Option<<Self::Item as ToOwned>::Owned>> {
self.iter().map(|x| x.map(|x| x.to_owned())).collect_vec()
}
}
impl<T: Array> ArrayToVecExt for T {}
pub trait ArrayBuilderPickExt: ArrayBuilder {
fn pick_from(&mut self, array: &Self::Array, logical_rows: &[usize]) {
for idx in logical_rows {
self.push(array.get(*idx));
}
}
fn pick_from_multiple(&mut self, arrays: &[&Self::Array], logical_rows: &[(usize, usize)]) {
for (idx, row) in logical_rows {
self.push(arrays[*idx].get(*row));
}
}
}
impl<T: ArrayBuilder> ArrayBuilderPickExt for T {}
pub trait ArrayImplBuilderPickExt {
fn pick_from(&mut self, array: &ArrayImpl, logical_rows: &[usize]);
fn pick_from_multiple(&mut self, arrays: &[ArrayImpl], logical_rows: &[(usize, usize)]);
}
pub trait ArraySortExt: Array
where
<Self as Array>::Item: PartialOrd,
{
fn get_sorted_indices(&self) -> Vec<usize> {
let mut sort_keys = (0..self.len())
.map(|x| self.get(x))
.enumerate()
.collect_vec();
sort_keys.sort_unstable_by(|a, b| {
use std::cmp::Ordering::*;
let a = a.1;
let b = b.1;
match (a, b) {
(None, None) => Equal,
(None, _) => Less,
(_, None) => Greater,
(a, b) => a.partial_cmp(&b).unwrap(),
}
});
sort_keys.into_iter().map(|x| x.0).collect_vec()
}
}
impl<T: Array> ArraySortExt for T where T::Item: PartialOrd {}
pub trait ArrayImplSortExt {
fn get_sorted_indices(&self) -> Vec<usize>;
}
macro_rules! impl_array_impl_shuffle_ext {
([], $( { $Abc:ident, $Type:ty, $abc:ident, $AbcArray:ty, $AbcArrayBuilder:ty, $Value:ident, $Pattern:pat } ),*) => {
impl ArrayImplBuilderPickExt for ArrayBuilderImpl {
fn pick_from(&mut self, array: &ArrayImpl, logical_rows: &[usize]) {
match (self, array) {
$(
(Self::$Abc(builder), ArrayImpl::$Abc(arr)) => builder.pick_from(arr, logical_rows),
)*
_ => panic!("failed to push value: type mismatch"),
}
}
fn pick_from_multiple(
&mut self,
arrays: &[ArrayImpl],
logical_rows: &[(usize, usize)],
) {
match self {
$(
Self::$Abc(builder) => {
let typed_arrays = arrays
.iter()
.map(|x| x.try_into().unwrap())
.collect::<SmallVec<[_; 8]>>();
builder.pick_from_multiple(&typed_arrays, logical_rows);
}
)*
}
}
}
impl ArrayImplSortExt for ArrayImpl {
fn get_sorted_indices(&self) -> Vec<usize> {
match self {
$(
Self::$Abc(a) => a.get_sorted_indices(),
)*
}
}
}
}
}
for_all_variants! { impl_array_impl_shuffle_ext }