cha_rs/
lib.rs

1mod error;
2use error::ExtractError;
3
4/// Extract the characters at the given indices from the input string.
5///
6/// # Examples
7///
8/// ```
9/// use cha_rs::*;
10/// let chars = extract("hello", &[1,5]).unwrap();
11/// assert_eq!(chars, &['h', 'o']);
12/// ```
13pub 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}