sedregex/
str_ext.rs

1pub trait StrExt {
2    fn char_at(&self, idx: usize) -> Option<char>;
3    fn previous(&self, idx: usize) -> Option<char>;
4}
5
6impl StrExt for str {
7    fn char_at(&self, at: usize) -> Option<char> {
8        self.char_indices()
9            .skip_while(|&(idx, _c)| idx < at)
10            .filter_map(|(idx, c)| if idx == at { Some(c) } else { None })
11            .next()
12    }
13
14    fn previous(&self, current: usize) -> Option<char> {
15        self.char_indices()
16            .skip_while(|&(idx, c)| idx + c.len_utf8() < current)
17            .filter_map(|(idx, c)| {
18                if idx + c.len_utf8() == current {
19                    Some(c)
20                } else {
21                    None
22                }
23            })
24            .next()
25    }
26}
27
28#[cfg(test)]
29mod test {
30    use super::*;
31
32    #[test]
33    fn various_len() {
34        let data = "абвГДеёlжз";
35        assert_eq!(Some('а'), data.char_at(0));
36        assert_eq!(Some('б'), data.char_at(2));
37        assert_eq!(Some('в'), data.char_at(4));
38        assert_eq!(Some('Г'), data.char_at(6));
39        assert_eq!(Some('Д'), data.char_at(8));
40        assert_eq!(Some('е'), data.char_at(10));
41        assert_eq!(Some('ё'), data.char_at(12));
42        assert_eq!(Some('l'), data.char_at(14));
43        assert_eq!(Some('ж'), data.char_at(15));
44        assert_eq!(Some('з'), data.char_at(17));
45        assert_eq!(None, data.previous(0));
46        assert_eq!(Some('а'), data.previous(2));
47        assert_eq!(Some('б'), data.previous(4));
48        assert_eq!(Some('в'), data.previous(6));
49        assert_eq!(Some('Г'), data.previous(8));
50        assert_eq!(Some('Д'), data.previous(10));
51        assert_eq!(Some('е'), data.previous(12));
52        assert_eq!(Some('ё'), data.previous(14));
53        assert_eq!(Some('l'), data.previous(15));
54        assert_eq!(Some('ж'), data.previous(17));
55    }
56
57    #[test]
58    fn boundary() {
59        let data = "ф";
60        assert_eq!(None, data.char_at(1));
61    }
62}