use crate::prelude::*;
use sorted_vec::SortedSet;
use super::utils::local_to_global;
pub trait SelectionDef
{
fn into_sel_index (
self,
sys: &(impl AtomPosAnalysis + BoxProvider), subset: Option<&[usize]>,
) -> Result<SVec, SelectionError>;
}
impl SelectionDef for &SelectionExpr
{
fn into_sel_index (
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
let ind = match subset {
None => self.apply_whole(sys)?,
Some(_) => {
Err(SelectionError::SelDefInSubsel)?
}
};
if ind.is_empty() {
Err(SelectionError::EmptyExpr(self.get_str().to_string()))
} else {
Ok(ind)
}
}
}
impl SelectionDef for &str
{
fn into_sel_index (
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
let expr = SelectionExpr::new(self)?;
let ind = match subset {
None => expr.apply_whole(sys)?,
Some(sub) => expr.apply_subset(sys, sub)?,
};
if ind.is_empty() {
Err(SelectionError::EmptyExpr(expr.get_str().to_string()))
} else {
Ok(ind)
}
}
}
impl SelectionDef for String
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.as_str().into_sel_index(sys, subset)
}
}
impl SelectionDef for &String
{
fn into_sel_index (
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.as_str().into_sel_index(sys, subset)
}
}
impl SelectionDef for std::ops::Range<usize>
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
let n = match subset {
None => sys.len(),
Some(sub) => sub.len(),
};
if self.start >= n || self.end > n {
return Err(SelectionError::IndexValidation(self.start, self.end, n-1));
}
match subset {
None => Ok(unsafe { SortedSet::from_sorted(self.collect::<Vec<_>>()) }),
Some(sub) => {
Ok(self.map(|i| sub[i]).collect::<Vec<_>>().into())
}
}
}
}
impl SelectionDef for std::ops::RangeInclusive<usize> {
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
if self.is_empty() {
Err(SelectionError::EmptyRange)
} else {
let (b, e) = self.into_inner();
(b..e + 1).into_sel_index(sys, subset)
}
}
}
impl SelectionDef for &[usize]
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
if self.is_empty() {
Err(SelectionError::EmptySlice)
} else {
match subset {
None => {
let v: SVec = self.to_vec().into();
let n = sys.len();
if v[0] >= n || v[v.len()-1] >= n {
Err(SelectionError::IndexValidation(v[0], v[v.len()-1], n-1))
} else {
Ok(v)
}
},
Some(sub) => local_to_global(self.into_iter().cloned(), sub),
}
}
}
}
impl SelectionDef for &Vec<usize>
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.as_slice().into_sel_index(sys, subset)
}
}
impl SelectionDef for Vec<usize>
{
fn into_sel_index (
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.as_slice().into_sel_index(sys, subset)
}
}
impl SelectionDef for SVec
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
if self.is_empty() {
Err(SelectionError::EmptySlice)
} else {
match subset {
None => {
let n = sys.len();
if self[self.len()-1] >= n {
Err(SelectionError::IndexValidation(self[0], self[self.len()-1], n-1))
} else {
Ok(self) }
},
Some(sub) => local_to_global(self.iter().cloned(), sub),
}
}
}
}
impl SelectionDef for &SVec
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.clone().into_sel_index(sys, subset)
}
}
impl SelectionDef for Sel
{
fn into_sel_index(
self,
sys: &(impl AtomPosAnalysis + BoxProvider),
subset: Option<&[usize]>,
) -> Result<SVec, SelectionError> {
self.0.into_sel_index(sys, subset)
}
}