1use std::fmt;
2use std::mem;
3
4#[derive(PartialEq, Eq, Copy, Clone, Debug)]
6pub enum BumpLevel {
7 Major,
8 Minor,
9 Patch,
10 None,
11}
12
13impl BumpLevel {
14 pub fn name(&self) -> &'static str {
16 match *self {
17 BumpLevel::Major => "Major",
18 BumpLevel::Minor => "Minor",
19 BumpLevel::Patch => "Patch",
20 BumpLevel::None => "None",
21 }
22 }
23}
24
25#[derive(PartialEq, Eq, Copy, Clone)]
27pub enum CommitType {
28 Breaking,
29 Feature,
30 Bugfix,
31 Other,
32 Meta,
33}
34
35pub struct CommitTypeIterator {
37 current: Option<CommitType>
38}
39
40impl CommitType {
41 pub fn first_variant() -> CommitType { CommitType::Breaking }
43
44 pub fn last_variant() -> CommitType { CommitType::Meta }
46
47 pub fn next_variant(&self) -> Option<CommitType> {
49 match *self {
50 CommitType::Breaking => Some(CommitType::Feature),
51 CommitType::Feature => Some(CommitType::Bugfix),
52 CommitType::Bugfix => Some(CommitType::Other),
53 CommitType::Other => Some(CommitType::Meta),
54 CommitType::Meta => None,
55 }
56 }
57
58 pub fn prev_variant(&self) -> Option<CommitType> {
60 match *self {
61 CommitType::Breaking => None,
62 CommitType::Feature => Some(CommitType::Breaking),
63 CommitType::Bugfix => Some(CommitType::Feature),
64 CommitType::Other => Some(CommitType::Bugfix),
65 CommitType::Meta => Some(CommitType::Other),
66 }
67 }
68
69 pub fn iter_variants() -> CommitTypeIterator {
71 CommitTypeIterator { current: Some(CommitType::first_variant()) }
72 }
73
74 pub fn emoji(&self) -> &'static str {
76 match *self {
77 CommitType::Breaking => "💥",
78 CommitType::Feature => "🎉",
79 CommitType::Bugfix => "🐛",
80 CommitType::Other => "🔥",
81 CommitType::Meta => "🌹",
82 }
83 }
84
85 pub fn bump_level(&self) -> BumpLevel {
87 match *self {
88 CommitType::Breaking => BumpLevel::Major,
89 CommitType::Feature => BumpLevel::Minor,
90 CommitType::Bugfix => BumpLevel::Patch,
91 CommitType::Other => BumpLevel::Patch,
92 CommitType::Meta => BumpLevel::None,
93 }
94 }
95
96 pub fn description(&self) -> &'static str {
98 match *self {
99 CommitType::Breaking => "Breaking change",
100 CommitType::Feature => "New functionality",
101 CommitType::Bugfix => "Bugfix",
102 CommitType::Other => "Cleanup / Performance",
103 CommitType::Meta => "Meta",
104 }
105 }
106}
107
108impl fmt::Debug for CommitType {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 write!(f, "CommitType {{ {} }}", self.emoji())
111 }
112}
113
114impl Iterator for CommitTypeIterator {
115 type Item = CommitType;
116
117 fn next(&mut self) -> Option<CommitType> {
118 match self.current {
119 Some(commit_type) => mem::replace(&mut self.current, commit_type.next_variant()),
120 None => None,
121 }
122 }
123
124 fn size_hint(&self) -> (usize, Option<usize>) {
125 match self.current {
126 Some(CommitType::Breaking) => (5, Some(5)),
127 Some(CommitType::Feature) => (4, Some(4)),
128 Some(CommitType::Bugfix) => (3, Some(3)),
129 Some(CommitType::Other) => (2, Some(2)),
130 Some(CommitType::Meta) => (1, Some(1)),
131 None => (0, Some(0)),
132 }
133 }
134}
135
136impl ExactSizeIterator for CommitTypeIterator {
137 fn len(&self) -> usize {
138 5
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::{CommitType, BumpLevel};
145
146 #[test]
147 fn it_gives_the_first_type() {
148 assert_eq!(CommitType::first_variant(), CommitType::Breaking);
149 }
150
151 #[test]
152 fn it_gives_the_last_type() {
153 assert_eq!(CommitType::last_variant(), CommitType::Meta);
154 }
155
156 #[test]
157 fn it_gives_the_next_type() {
158 assert_eq!(CommitType::Breaking.next_variant(), Some(CommitType::Feature));
159 assert_eq!(CommitType::Feature.next_variant(), Some(CommitType::Bugfix));
160 assert_eq!(CommitType::Bugfix.next_variant(), Some(CommitType::Other));
161 assert_eq!(CommitType::Other.next_variant(), Some(CommitType::Meta));
162 assert_eq!(CommitType::Meta.next_variant(), None);
163 }
164
165 #[test]
166 fn it_gives_the_previous_type() {
167 assert_eq!(CommitType::Breaking.prev_variant(), None);
168 assert_eq!(CommitType::Feature.prev_variant(), Some(CommitType::Breaking));
169 assert_eq!(CommitType::Bugfix.prev_variant(), Some(CommitType::Feature));
170 assert_eq!(CommitType::Other.prev_variant(), Some(CommitType::Bugfix));
171 assert_eq!(CommitType::Meta.prev_variant(), Some(CommitType::Other));
172 }
173
174 #[test]
175 fn it_gives_an_variant_iterator() {
176 let mut iter = CommitType::iter_variants();
177
178 assert_eq!(iter.next(), Some(CommitType::Breaking));
179 assert_eq!(iter.next(), Some(CommitType::Feature));
180 assert_eq!(iter.next(), Some(CommitType::Bugfix));
181 assert_eq!(iter.next(), Some(CommitType::Other));
182 assert_eq!(iter.next(), Some(CommitType::Meta));
183 assert_eq!(iter.next(), None);
184 }
185
186 #[test]
187 fn it_gives_an_emoji() {
188 assert_eq!(CommitType::Breaking.emoji(), "💥");
189 assert_eq!(CommitType::Feature.emoji(), "🎉");
190 assert_eq!(CommitType::Bugfix.emoji(), "🐛");
191 assert_eq!(CommitType::Other.emoji(), "🔥");
192 assert_eq!(CommitType::Meta.emoji(), "🌹");
193 }
194
195 #[test]
196 fn it_gives_a_bump_level() {
197 assert_eq!(CommitType::Breaking.bump_level(), BumpLevel::Major);
198 assert_eq!(CommitType::Feature.bump_level(), BumpLevel::Minor);
199 assert_eq!(CommitType::Bugfix.bump_level(), BumpLevel::Patch);
200 assert_eq!(CommitType::Other.bump_level(), BumpLevel::Patch);
201 assert_eq!(CommitType::Meta.bump_level(), BumpLevel::None);
202 }
203
204 #[test]
205 fn it_gives_a_bump_level_name() {
206 assert_eq!(CommitType::Breaking.bump_level().name(), "Major");
207 assert_eq!(CommitType::Feature.bump_level().name(), "Minor");
208 assert_eq!(CommitType::Bugfix.bump_level().name(), "Patch");
209 assert_eq!(CommitType::Meta.bump_level().name(), "None");
210 }
211
212 #[test]
213 fn it_gives_a_description() {
214 assert_eq!(CommitType::Breaking.description(), "Breaking change");
215 assert_eq!(CommitType::Feature.description(), "New functionality");
216 assert_eq!(CommitType::Bugfix.description(), "Bugfix");
217 assert_eq!(CommitType::Other.description(), "Cleanup / Performance");
218 assert_eq!(CommitType::Meta.description(), "Meta");
219 }
220}