perspective_client/config/
sort.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::fmt::Display;
14
15use serde::{Deserialize, Serialize};
16use ts_rs::TS;
17
18use crate::proto;
19
20#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Serialize, TS)]
21#[serde()]
22pub struct Sort(pub String, pub SortDir);
23
24#[derive(Clone, Copy, Deserialize, Debug, Eq, PartialEq, Serialize, TS)]
25#[serde()]
26pub enum SortDir {
27    #[serde(rename = "none")]
28    None,
29
30    #[serde(rename = "desc")]
31    Desc,
32
33    #[serde(rename = "asc")]
34    Asc,
35
36    #[serde(rename = "col desc")]
37    ColDesc,
38
39    #[serde(rename = "col asc")]
40    ColAsc,
41
42    #[serde(rename = "desc abs")]
43    DescAbs,
44
45    #[serde(rename = "asc abs")]
46    AscAbs,
47
48    #[serde(rename = "col desc abs")]
49    ColDescAbs,
50
51    #[serde(rename = "col asc abs")]
52    ColAscAbs,
53}
54
55impl Display for SortDir {
56    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
57        write!(fmt, "{}", match self {
58            Self::None => "none",
59            Self::Desc => "desc",
60            Self::Asc => "asc",
61            Self::ColDesc => "col desc",
62            Self::ColAsc => "col asc",
63            Self::DescAbs => "desc abs",
64            Self::AscAbs => "asc abs",
65            Self::ColDescAbs => "col desc abs",
66            Self::ColAscAbs => "col asc abs",
67        })
68    }
69}
70
71impl SortDir {
72    /// Increment the `SortDir` in logical order, given an `abs()` modifier.
73    pub fn cycle(&self, split_by: bool, abs: bool) -> Self {
74        let order: &[Self] = match (split_by, abs) {
75            (false, false) => &[Self::None, Self::Asc, Self::Desc],
76            (false, true) => &[Self::None, Self::AscAbs, Self::DescAbs],
77            (true, false) => &[
78                Self::None,
79                Self::Asc,
80                Self::Desc,
81                Self::ColAsc,
82                Self::ColDesc,
83            ],
84            (true, true) => &[
85                Self::None,
86                Self::AscAbs,
87                Self::DescAbs,
88                Self::ColAscAbs,
89                Self::ColDescAbs,
90            ],
91        };
92
93        let index = order.iter().position(|x| x == self).unwrap_or(0);
94        order[(index + 1) % order.len()]
95    }
96}
97
98impl From<SortDir> for proto::SortOp {
99    fn from(value: SortDir) -> Self {
100        match value {
101            SortDir::None => proto::SortOp::SortNone,
102            SortDir::Desc => proto::SortOp::SortDesc,
103            SortDir::Asc => proto::SortOp::SortAsc,
104            SortDir::ColDesc => proto::SortOp::SortColDesc,
105            SortDir::ColAsc => proto::SortOp::SortColAsc,
106            SortDir::DescAbs => proto::SortOp::SortDescAbs,
107            SortDir::AscAbs => proto::SortOp::SortAscAbs,
108            SortDir::ColDescAbs => proto::SortOp::SortColDescAbs,
109            SortDir::ColAscAbs => proto::SortOp::SortColAscAbs,
110        }
111    }
112}
113
114impl From<proto::SortOp> for SortDir {
115    fn from(value: proto::SortOp) -> Self {
116        match value {
117            proto::SortOp::SortNone => SortDir::None,
118            proto::SortOp::SortDesc => SortDir::Desc,
119            proto::SortOp::SortAsc => SortDir::Asc,
120            proto::SortOp::SortColAsc => SortDir::ColAsc,
121            proto::SortOp::SortColDesc => SortDir::ColDesc,
122            proto::SortOp::SortAscAbs => SortDir::AscAbs,
123            proto::SortOp::SortDescAbs => SortDir::DescAbs,
124            proto::SortOp::SortColAscAbs => SortDir::ColAscAbs,
125            proto::SortOp::SortColDescAbs => SortDir::ColDescAbs,
126        }
127    }
128}
129
130impl From<Sort> for proto::view_config::Sort {
131    fn from(value: Sort) -> Self {
132        proto::view_config::Sort {
133            column: value.0,
134            op: proto::SortOp::from(value.1).into(),
135        }
136    }
137}
138
139impl From<proto::view_config::Sort> for Sort {
140    fn from(value: proto::view_config::Sort) -> Self {
141        Sort(
142            value.column,
143            proto::SortOp::try_from(value.op).unwrap().into(),
144        )
145    }
146}