1use regex::{Captures, Regex};
2use std::collections::HashMap;
3
4fn extract_regex(x: String) -> (String, String) {
5 let re: Regex = Regex::new(r"(?x)(?P<name>.*)\.(?P<frames>\d{2,9})\.(?P<ext>\w{2,5})$").unwrap();
6 let result_caps: Option<Captures> = re.captures(&x);
7 match result_caps {
8 None => (x, "None".to_string()),
9 caps_wrap => {
10 let caps = caps_wrap.unwrap();
11 let string_list = vec![
12 caps["name"].to_string(),
13 "*".to_string(),
14 caps["ext"].to_string(),
15 ];
16 let key: String = string_list.join(".");
17 (key, caps["frames"].to_string())
18 }
19 }
20}
21#[test]
22fn test_handle_none() {
23 let source: String = "foobar.exr".to_string();
24 let expected: (String, String) = (source.clone(), "None".to_string());
25 assert_eq!(expected, extract_regex(source))
26}
27
28fn parse_result(dir_scan: Vec<String>) -> HashMap<String, Vec<String>> {
29 let mut book_reviews: HashMap<String, Vec<String>> = HashMap::new();
30 for x in dir_scan {
31 let extraction: (String, String) = extract_regex(x);
32 let vec1: Vec<String> = vec![extraction.1.clone()];
33 book_reviews
34 .entry(extraction.0)
35 .and_modify(|value| (*value).push(extraction.1))
36 .or_insert(vec1);
37 }
38 book_reviews
39}
40#[test]
41fn test_parse_string() {
42 let source = vec![
43 "toto.001.tiff".to_string(),
44 "toto.002.tiff".to_string(),
45 "foo.exr".to_string(),
46 ];
47 let vec_toto: Vec<String> = vec!["001".to_string(), "002".to_string()];
48 let vec_foo: Vec<String> = vec!["None".to_string()];
49 let expected: HashMap<String, Vec<String>> = HashMap::from([
50 ("toto.*.tiff".to_string(), vec_toto),
51 ("foo.exr".to_string(), vec_foo),
52 ]);
53 assert_eq!(expected, parse_result(source));
54}
55
56fn convert_vec(frames_vec: Vec<String>) -> Vec<isize> {
57 frames_vec
58 .into_iter()
59 .map(|x: String| x.parse::<isize>().unwrap())
60 .collect()
61}
62
63#[test]
64fn test_convert_vec() {
65 let source: Vec<String> = vec!["001".to_string(), "003".to_string()];
66 let expected: Vec<isize> = vec![1, 3];
67 assert_eq!(expected, convert_vec(source));
68}
69
70fn group_continuity(data: &[isize]) -> Vec<Vec<isize>> {
71 let mut slice_start: usize = 0;
72 let mut result: Vec<&[isize]> = Vec::new();
73 for i in 1..data.len() {
74 if data[i - 1] + 1 != data[i] {
75 result.push(&data[slice_start..i]);
76 slice_start = i;
77 }
78 }
79 if data.len() > 0 {
80 result.push(&data[slice_start..]);
81 }
82 result.iter().map(|x| x.to_vec()).collect()
83}
84#[test]
85fn test_continuity() {
86 let source: Vec<isize> = vec![1, 2, 3, 5, 6, 7, 11, 12];
87 let expected: Vec<Vec<isize>> = vec![vec![1, 2, 3], vec![5, 6, 7], vec![11, 12]];
88 assert_eq!(expected, group_continuity(&source));
89}
90fn convert_vec_to_str(input_vec: Vec<Vec<isize>>) -> String {
91 let mut tmp_vec: Vec<String> = Vec::new();
92 for x in input_vec {
93 if x.len() == 1 {
94 tmp_vec.push(x[0].to_string());
95 } else {
96 tmp_vec.push(format!("{}-{}", x.first().unwrap(), x.last().unwrap()))
97 }
98 }
99 tmp_vec.join(",")
100}
101#[test]
102fn test_convert_vec_to_str() {
103 let source: Vec<Vec<isize>> = vec![vec![1, 2, 3], vec![5, 6, 7], vec![11, 12], vec![45]];
104 let expected: String = "1-3,5-7,11-12,45".to_string();
105 assert_eq!(expected, convert_vec_to_str(source));
106}
107
108pub fn run(frames: Vec<String>) -> Vec<String> {
109 let frames_dict: HashMap<String, Vec<String>> = parse_result(frames);
110 let mut out_frames: Vec<String> = Vec::new();
111 for (key, value) in frames_dict {
112 if value[0] == "None" && value.len() == 1 {
113 out_frames.push(key);
114 } else {
115 let i = convert_vec(value);
116 let j = group_continuity(&i);
117 let k = convert_vec_to_str(j);
118 out_frames.push(format!("{}@{}", key, k));
119 }
120 }
121 out_frames
122}