1use arrayvec::ArrayVec;
2
3#[cfg(test)]
4mod mod_test_includes;
5
6pub(crate) mod transformations;
7
8#[derive(Debug, PartialEq, Clone)]
9pub enum Operation {
10 Blur(f32),
11 Brighten(i32),
12 Contrast(f32),
13 Crop(u32, u32, u32, u32),
14 Filter3x3(ArrayVec<[f32; 9]>),
15 FlipHorizontal,
16 FlipVertical,
17 GrayScale,
18 HueRotate(i32),
19 Invert,
20 Resize(u32, u32),
21 Rotate90,
22 Rotate180,
23 Rotate270,
24 Unsharpen(f32, i32),
25}
26
27pub enum OpArg {
28 Empty,
29 FloatingPoint(f32),
30 Integer(i32),
31 UnsignedIntegerTuple2(u32, u32),
32 UnsignedIntegerTuple4(u32, u32, u32, u32),
33 FloatingPointArrayVec9(ArrayVec<[f32; 9]>),
34 FloatingPointIntegerTuple2(f32, i32),
35}
36
37pub fn operation_by_name(name: &str, value: OpArg) -> Result<Operation, String> {
38 match (name, value) {
39 ("blur", OpArg::FloatingPoint(v)) => Ok(Operation::Blur(v)),
40 ("brighten", OpArg::Integer(v)) => Ok(Operation::Brighten(v)),
41 ("contrast", OpArg::FloatingPoint(v)) => Ok(Operation::Contrast(v)),
42 ("crop", OpArg::UnsignedIntegerTuple4(u0, u1, u2, u3)) => {
43 Ok(Operation::Crop(u0, u1, u2, u3))
44 }
45 ("filter3x3", OpArg::FloatingPointArrayVec9(v)) => Ok(Operation::Filter3x3(v)),
46 ("fliph", OpArg::Empty) => Ok(Operation::FlipHorizontal),
47 ("flipv", OpArg::Empty) => Ok(Operation::FlipVertical),
48 ("grayscale", OpArg::Empty) => Ok(Operation::GrayScale),
49 ("huerotate", OpArg::Integer(v)) => Ok(Operation::HueRotate(v)),
50 ("invert", OpArg::Empty) => Ok(Operation::Invert),
51 ("resize", OpArg::UnsignedIntegerTuple2(u0, u1)) => Ok(Operation::Resize(u0, u1)),
52 ("rotate90", OpArg::Empty) => Ok(Operation::Rotate90),
53 ("rotate180", OpArg::Empty) => Ok(Operation::Rotate180),
54 ("rotate270", OpArg::Empty) => Ok(Operation::Rotate270),
55 ("unsharpen", OpArg::FloatingPointIntegerTuple2(f, i)) => Ok(Operation::Unsharpen(f, i)),
56 _ => Err("No suitable operation was found.".to_string()),
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
68 fn blur_ok() {
69 let actual = operation_by_name("blur", OpArg::FloatingPoint(1.5));
70
71 assert_eq!(actual, Ok(Operation::Blur(1.5)));
72 }
73
74 #[test]
75 fn blur_name_err() {
76 let actual = operation_by_name("blur'", OpArg::FloatingPoint(1.5));
77
78 assert_ne!(actual, Ok(Operation::Blur(1.5)));
79 }
80
81 #[test]
82 fn blur_arg_err() {
83 let actual = operation_by_name("blur", OpArg::Empty);
84
85 assert_ne!(actual, Ok(Operation::Blur(1.5)));
86 }
87
88 #[test]
92 fn brighten_ok() {
93 let actual = operation_by_name("brighten", OpArg::Integer(-25));
94
95 assert_eq!(actual, Ok(Operation::Brighten(-25)));
96 }
97
98 #[test]
102 fn contrast_ok() {
103 let actual = operation_by_name("contrast", OpArg::FloatingPoint(1.5));
104
105 assert_eq!(actual, Ok(Operation::Contrast(1.5)));
106 }
107
108 #[test]
112 fn crop_ok() {
113 let actual = operation_by_name("crop", OpArg::UnsignedIntegerTuple4(0, 1, 2, 3));
114
115 assert_eq!(actual, Ok(Operation::Crop(0, 1, 2, 3)));
116 }
117
118 #[test]
122 fn filter3x3_ok() {
123 let array = ArrayVec::<[f32; 9]>::default();
124
125 let actual = operation_by_name("filter3x3", OpArg::FloatingPointArrayVec9(array));
126
127 assert_eq!(
128 actual,
129 Ok(Operation::Filter3x3(ArrayVec::<[f32; 9]>::default()))
130 );
131 }
132
133 #[test]
137 fn fliph_ok() {
138 let actual = operation_by_name("fliph", OpArg::Empty);
139
140 assert_eq!(actual, Ok(Operation::FlipHorizontal));
141 }
142
143 #[test]
147 fn flipv_ok() {
148 let actual = operation_by_name("flipv", OpArg::Empty);
149
150 assert_eq!(actual, Ok(Operation::FlipVertical));
151 }
152
153 #[test]
157 fn grayscale_ok() {
158 let actual = operation_by_name("grayscale", OpArg::Empty);
159
160 assert_eq!(actual, Ok(Operation::GrayScale));
161 }
162
163 #[test]
167 fn huerotate_ok() {
168 let actual = operation_by_name("huerotate", OpArg::Integer(-399));
169
170 assert_eq!(actual, Ok(Operation::HueRotate(-399)));
171 }
172
173 #[test]
177 fn invert_ok() {
178 let actual = operation_by_name("invert", OpArg::Empty);
179
180 assert_eq!(actual, Ok(Operation::Invert));
181 }
182
183 #[test]
187 fn resize_ok() {
188 let actual = operation_by_name("resize", OpArg::UnsignedIntegerTuple2(80, 40));
189
190 assert_eq!(actual, Ok(Operation::Resize(80, 40)));
191 }
192
193 #[test]
197 fn rotate90_ok() {
198 let actual = operation_by_name("rotate90", OpArg::Empty);
199
200 assert_eq!(actual, Ok(Operation::Rotate90));
201 }
202
203 #[test]
207 fn rotate180_ok() {
208 let actual = operation_by_name("rotate180", OpArg::Empty);
209
210 assert_eq!(actual, Ok(Operation::Rotate180));
211 }
212
213 #[test]
217 fn rotate270_ok() {
218 let actual = operation_by_name("rotate270", OpArg::Empty);
219
220 assert_eq!(actual, Ok(Operation::Rotate270));
221 }
222
223 #[test]
227 fn unsharpen_ok() {
228 let actual = operation_by_name("unsharpen", OpArg::FloatingPointIntegerTuple2(1.5, 3));
229
230 assert_eq!(actual, Ok(Operation::Unsharpen(1.5, 3)));
231 }
232}