use {
crate::{
col::Col,
order::Order,
},
lfs_core::Mount,
std::{
error,
fmt,
str::FromStr,
},
};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Sorting {
col: Col,
order: Order,
}
impl Default for Sorting {
fn default() -> Self {
let col = Col::default_sort_col();
let order = col.default_sort_order();
Self { col, order }
}
}
impl Sorting {
pub fn sort(
self,
mounts: &mut [Mount],
) {
let comparator = self.col.comparator();
mounts.sort_by(comparator);
if self.order == Order::Desc {
mounts.reverse();
}
}
}
#[derive(Debug)]
pub struct ParseSortingError {
raw: String,
reason: String,
}
impl ParseSortingError {
pub fn new<S: Into<String>, E: ToString>(
raw: S,
reason: E,
) -> Self {
Self {
raw: raw.into(),
reason: reason.to_string(),
}
}
}
impl fmt::Display for ParseSortingError {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
write!(
f,
"{:?} can't be parsed as a sort expression because {}",
self.raw, self.reason
)
}
}
impl error::Error for ParseSortingError {}
impl FromStr for Sorting {
type Err = ParseSortingError;
fn from_str(s: &str) -> Result<Self, ParseSortingError> {
let cut_idx_len = s
.char_indices()
.find(|(_idx, c)| c.is_whitespace() || *c == '-')
.map(|(idx, c)| (idx, c.len_utf8()));
let (s_col, s_order) = match cut_idx_len {
Some((idx, len)) => (&s[..idx], Some(&s[idx + len..])),
None => (s, None),
};
let col: Col = s_col
.parse()
.map_err(|pce| ParseSortingError::new(s, Box::new(pce)))?;
let order = match s_order {
Some(s_order) => s_order
.parse()
.map_err(|poe| ParseSortingError::new(s, Box::new(poe)))?,
None => col.default_sort_order(),
};
Ok(Self { col, order })
}
}