1use crate::error::{MyError, MyResult};
2use indexmap::IndexSet;
3
4#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5pub enum DirKind {
6 Asc,
7 Desc,
8}
9
10#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
11pub enum OrderKind {
12 Dir,
13 Group,
14 Name,
15 Ext,
16 Size(DirKind),
17 Time(DirKind),
18}
19
20impl OrderKind {
21 fn from_char(ch: char) -> Option<Self> {
22 match ch {
23 'd' => Some(Self::Dir),
24 'n' => Some(Self::Name),
25 'e' => Some(Self::Ext),
26 's' => Some(Self::Size(DirKind::Asc)),
27 't' => Some(Self::Time(DirKind::Asc)),
28 _ => None,
29 }
30 }
31
32 pub fn ascending(self: Self) -> Self {
33 match self {
34 Self::Size(_) => Self::Size(DirKind::Asc),
35 Self::Time(_) => Self::Time(DirKind::Asc),
36 any => any,
37 }
38 }
39
40 pub fn descending(self: Self) -> Self {
41 match self {
42 Self::Size(_) => Self::Size(DirKind::Desc),
43 Self::Time(_) => Self::Time(DirKind::Desc),
44 any => any,
45 }
46 }
47}
48
49#[derive(Clone)]
50pub struct OrderVec {
51 pub inner: Vec<OrderKind>,
52}
53
54impl OrderVec {
55 pub fn from_str(value: &str) -> MyResult<Self> {
56 let mut results = IndexSet::new();
57 let mut result = None;
58 for ch in value.chars() {
59 if ch.is_alphabetic() {
60 if let Some(result) = result {
61 results.insert(result);
62 }
63 result = OrderKind::from_char(ch);
64 if result == None {
65 return Err(MyError::create_clap("order", value));
66 }
67 } else if ch == '+' {
68 result = result.map(|x| x.ascending());
69 } else if ch == '-' {
70 result = result.map(|x| x.descending());
71 } else {
72 return Err(MyError::create_clap("order", value));
73 }
74 }
75 if let Some(result) = result {
76 results.insert(result);
77 }
78 let results = Self { inner: results.into_iter().collect() };
79 Ok(results)
80 }
81}