1#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2pub struct TextRange {
3 start_index: usize,
4 end_index: usize,
5}
6
7impl TextRange {
8 pub fn new(start_index: usize, end_index: usize) -> Self {
9 Self {
10 start_index,
11 end_index,
12 }
13 }
14
15 pub fn start_index(&self) -> usize {
16 self.start_index
17 }
18
19 pub fn end_index(&self) -> usize {
20 self.end_index
21 }
22
23 pub fn len(&self) -> usize {
24 self.end_index - self.start_index
25 }
26
27 pub fn extract<'a>(&self, text: &'a str) -> Option<&'a str> {
28 text.get(self.start_index..self.end_index)
29 }
30}
31
32#[cfg(test)]
33mod tests {
34 use crate::TextRange;
35
36 #[test]
37 fn test_len() {
38 let range = TextRange::new(1, 2);
39
40 let result = range.len();
41
42 assert_eq!(result, 1);
43 }
44
45 #[test]
46 fn test_extract_ascii() {
47 let text = "hello world";
48 let range = TextRange::new(1, 2);
49
50 let result = range.extract(text);
51
52 assert_eq!(result, Some("e"));
53 }
54
55 #[test]
56 fn test_extract_unicode() {
57 let text = "你好世界";
58 let range = TextRange::new(3, 6);
59
60 let result = range.extract(text);
61
62 assert_eq!(result, Some("好"));
63 }
64
65 #[test]
66 fn test_extract_invalid_text() {
67 let text = "你好世界";
68 let range = TextRange::new(0, 1);
69
70 let result = range.extract(text);
71
72 assert_eq!(result, None);
73 }
74}