1mod error;
2use error::ExtractError;
3
4pub fn extract(input: &str, indices: &[usize]) -> Result<Vec<char>, ExtractError> {
14 if indices.is_empty() {
15 return Err(ExtractError::NoIndices);
16 }
17 if indices.iter().any(|i| i == &0 || i > &input.len()) {
18 return Err(ExtractError::OutOfRange(input.len()));
19 }
20
21 let c: Vec<char> = input
22 .chars()
23 .enumerate()
24 .filter(|&(i, _)| indices.contains(&(i + 1)))
25 .map(|(_, c)| c)
26 .collect();
27 Ok(c)
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33
34 #[test]
35 fn test_extract() {
36 let got = extract("hello", &[1, 3, 5]).unwrap();
37 assert_eq!(got, &['h', 'l', 'o']);
38 }
39
40 #[test]
41 fn test_extract_out_of_range_low() {
42 let got = extract("hello", &[0]);
43 assert!(got.is_err())
44 }
45
46 #[test]
47 fn test_extract_out_of_range_high() {
48 let got = extract("hello", &[6]);
49 assert!(got.is_err())
50 }
51
52 #[test]
53 fn test_extract_some_inputs_out_of_range() {
54 let got = extract("hello", &[3, 5, 6]);
55 assert!(got.is_err())
56 }
57
58 #[test]
59 fn test_extract_empty_indices() {
60 let got = extract("hello", &[]);
61 assert!(got.is_err())
62 }
63
64 #[test]
65 fn test_extract_empty_input() {
66 let got = extract("", &[1, 3, 5]);
67 assert!(got.is_err())
68 }
69}