#[derive(Debug)]
pub struct InsufficientSize {
_err_index: usize,
}
impl InsufficientSize {
pub fn new(err_index: usize) -> Self {
Self {
_err_index: err_index,
}
}
}
pub trait Selector {
fn select_mode(&self) -> Vec<Vec<usize>>;
}
pub trait Select<T> {
fn select_one_list(&self, select_list: &[usize]) -> Vec<Option<&T>>;
fn select<U: Selector>(&self, select_group: &U) -> Vec<Vec<Option<&T>>> {
select_group
.select_mode()
.into_iter()
.map(|s| self.select_one_list(&s))
.collect()
}
fn try_select<U: Selector>(&self, select_group: &U) -> Result<Vec<Vec<&T>>, InsufficientSize> {
let res: Vec<Result<Vec<&T>, usize>> = select_group
.select_mode()
.into_iter()
.map(|list| {
match self
.select_one_list(&list)
.iter()
.enumerate()
.find(|(_, v)| v.is_none())
{
Some((index, _)) => Err(index),
None => Ok(self
.select_one_list(&list)
.into_iter()
.map(|v| v.unwrap())
.collect::<Vec<&T>>()),
}
})
.collect();
match res.iter().enumerate().find(|(_, v)| v.is_err()) {
Some((index, _)) => Err(InsufficientSize::new(index)),
None => Ok(res.into_iter().map(|list| list.unwrap()).collect()),
}
}
}
impl<T, const N: usize> Select<T> for [T; N] {
fn select_one_list(&self, select_list: &[usize]) -> Vec<Option<&T>> {
select_list.iter().map(|&i| self.get(i)).collect()
}
}
macro_rules! select_impl {
($b:ident, $t:ty) => {
impl<$b> Select<$b> for $t {
fn select_one_list(&self, select_list: &[usize]) -> Vec<Option<&T>> {
select_list.iter().map(|&i| self.get(i)).collect()
}
}
};
($b:ident, $($t:ty),*) => {
$(select_impl!($b, $t);)*
};
}
select_impl!(T, &[T], Vec<T>, [T]);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_select_from_str_list() {
let str_list = ["hi", "i", "am", "roger", "and", "you"];
let select_list = [1, 2, 3, 7, 2, 3, 0];
let res = str_list.select_one_list(&select_list);
for v in res {
println!("{:#?}", v);
}
}
struct CustomSelector;
impl Selector for CustomSelector {
fn select_mode(&self) -> Vec<Vec<usize>> {
vec![vec![0, 0, 0], vec![1, 1, 1], vec![2, 2, 2]]
}
}
#[test]
fn test_custom_selector() {
let str_list = ["hi", "i", "am", "roger", "and", "you"];
let res = str_list.try_select(&CustomSelector).unwrap();
println!("{:#?}", res);
}
}