1use {
2 crate::{
3 col::Col,
4 order::Order,
5 },
6 lfs_core::Mount,
7 std::{
8 error,
9 fmt,
10 str::FromStr,
11 },
12};
13
14#[derive(Debug, Clone, Copy, PartialEq)]
16pub struct Sorting {
17 col: Col,
18 order: Order,
19}
20
21impl Default for Sorting {
22 fn default() -> Self {
23 let col = Col::default_sort_col();
24 let order = col.default_sort_order();
25 Self { col, order }
26 }
27}
28
29impl Sorting {
30 pub fn sort(self, mounts: &mut [Mount]) {
31 let comparator = self.col.comparator();
32 mounts.sort_by(comparator);
33 if self.order == Order::Desc {
34 mounts.reverse();
35 }
36 }
37}
38
39#[derive(Debug)]
40pub struct ParseSortingError {
41 raw: String,
42 reason: String,
43}
44impl ParseSortingError {
45 pub fn new<S: Into<String>, E: ToString>(raw: S, reason: E) -> Self {
46 Self {
47 raw: raw.into(),
48 reason: reason.to_string(),
49 }
50 }
51}
52impl fmt::Display for ParseSortingError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 write!(f, "{:?} can't be parsed as a sort expression because {}", self.raw, self.reason)
55 }
56}
57impl error::Error for ParseSortingError {}
58
59impl FromStr for Sorting {
60 type Err = ParseSortingError;
61 fn from_str(s: &str) -> Result<Self, ParseSortingError> {
62 let cut_idx_len = s
63 .char_indices()
64 .find(|(_idx, c)| c.is_whitespace() || *c == '-')
65 .map(|(idx, c)| (idx, c.len_utf8()));
66 let (s_col, s_order) = match cut_idx_len {
67 Some((idx, len)) => (&s[..idx], Some(&s[idx+len..])),
68 None => (s, None),
69 };
70 let col: Col = s_col.parse()
71 .map_err(|pce| ParseSortingError::new(s, Box::new(pce)))?;
72 let order = match s_order {
73 Some(s_order) => {
74 s_order.parse()
75 .map_err(|poe| ParseSortingError::new(s, Box::new(poe)))?
76 }
77 None => {
78 col.default_sort_order()
79 }
80 };
81 Ok(Self { col, order })
82 }
83}