1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::{error::Error, fmt, str::FromStr, string::ToString};
pub trait Order {
fn with_order(self, order: Direction) -> Self;
fn order(&self) -> Option<Direction>;
}
macro_rules! impl_order {
($name:path) => {
impl Order for $name {
fn with_order(mut self, order: Direction) -> $name {
self.order = Some(order);
self
}
fn order(&self) -> Option<Direction> {
self.order
}
}
};
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Direction {
Asc,
Desc,
}
impl ToString for Direction {
fn to_string(&self) -> String {
match *self {
Direction::Asc => "asc".to_string(),
Direction::Desc => "desc".to_string(),
}
}
}
#[derive(Debug)]
pub struct ParseDirectionError {
kind: ErrorKind,
}
#[derive(Debug)]
enum ErrorKind {
InvalidToken,
}
impl Error for ParseDirectionError {
fn description(&self) -> &str {
match self.kind {
ErrorKind::InvalidToken => "Invalid token specified",
}
}
}
impl fmt::Display for ParseDirectionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.description())
}
}
impl FromStr for Direction {
type Err = ParseDirectionError;
fn from_str(s: &str) -> Result<Direction, Self::Err> {
match s.to_lowercase().as_ref() {
"asc" => Ok(Direction::Asc),
"desc" => Ok(Direction::Desc),
_ => Err(ParseDirectionError {
kind: ErrorKind::InvalidToken,
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_can_become_a_string() {
assert_eq!(Direction::Asc.to_string(), "asc");
assert_eq!(Direction::Desc.to_string(), "desc");
}
#[test]
fn it_can_be_derived() {
struct Foo {
order: Option<Direction>,
}
impl_order!(Foo);
let foo = Foo { order: None }.with_order(Direction::Asc);
assert_eq!(foo.order, Some(Direction::Asc));
assert_eq!(foo.order(), Some(Direction::Asc));
}
#[test]
fn it_can_be_parsed() {
assert_eq!("asc".parse::<Direction>().unwrap(), Direction::Asc);
assert_eq!("aSc".parse::<Direction>().unwrap(), Direction::Asc);
assert_eq!("desc".parse::<Direction>().unwrap(), Direction::Desc);
assert_eq!("DESC".parse::<Direction>().unwrap(), Direction::Desc);
assert!("no".parse::<Direction>().is_err());
}
}