]> git.lizzy.rs Git - rust.git/blob - src/text.rs
ac1a54a7582025381f02fa4446043f0e36542eea
[rust.git] / src / text.rs
1 use std::fmt;
2 use std::ops;
3
4 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5 pub struct TextUnit(u32);
6
7 impl TextUnit {
8     pub fn len_of_char(c: char) -> TextUnit {
9         TextUnit(c.len_utf8() as u32)
10     }
11
12     pub fn new(val: u32) -> TextUnit {
13         TextUnit(val)
14     }
15 }
16
17 impl fmt::Debug for TextUnit {
18     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19         <Self as fmt::Display>::fmt(self, f)
20     }
21 }
22
23 impl fmt::Display for TextUnit {
24     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25         self.0.fmt(f)
26     }
27 }
28
29 impl From<TextUnit> for u32 {
30     fn from(tu: TextUnit) -> u32 {
31         tu.0
32     }
33 }
34
35 impl From<u32> for TextUnit {
36     fn from(tu: u32) -> TextUnit {
37         TextUnit::new(tu)
38     }
39 }
40
41 impl ops::Add<TextUnit> for TextUnit {
42     type Output = TextUnit;
43     fn add(self, rhs: TextUnit) -> TextUnit {
44         TextUnit(self.0 + rhs.0)
45     }
46 }
47
48 impl ops::AddAssign<TextUnit> for TextUnit {
49     fn add_assign(&mut self, rhs: TextUnit) {
50         self.0 += rhs.0
51     }
52 }
53
54 impl ops::Sub<TextUnit> for TextUnit {
55     type Output = TextUnit;
56     fn sub(self, rhs: TextUnit) -> TextUnit {
57         TextUnit(self.0 - rhs.0)
58     }
59 }
60
61 impl ops::SubAssign<TextUnit> for TextUnit {
62     fn sub_assign(&mut self, rhs: TextUnit) {
63         self.0 -= rhs.0
64     }
65 }
66
67 #[derive(Clone, Copy, PartialEq, Eq)]
68 pub struct TextRange {
69     start: TextUnit,
70     end: TextUnit,
71 }
72
73 impl fmt::Debug for TextRange {
74     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75         <Self as fmt::Display>::fmt(self, f)
76     }
77 }
78
79 impl fmt::Display for TextRange {
80     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81         write!(f, "[{}; {})", self.start(), self.end())
82     }
83 }
84
85 impl TextRange {
86     pub fn empty() -> TextRange {
87         TextRange::from_to(TextUnit::new(0), TextUnit::new(0))
88     }
89
90     pub fn from_to(from: TextUnit, to: TextUnit) -> TextRange {
91         assert!(from <= to, "Invalid text range [{}; {})", from, to);
92         TextRange {
93             start: from,
94             end: to,
95         }
96     }
97
98     pub fn from_len(from: TextUnit, len: TextUnit) -> TextRange {
99         TextRange::from_to(from, from + len)
100     }
101
102     pub fn start(&self) -> TextUnit {
103         self.start
104     }
105
106     pub fn end(&self) -> TextUnit {
107         self.end
108     }
109
110     pub fn len(&self) -> TextUnit {
111         self.end - self.start
112     }
113
114     pub fn is_empty(&self) -> bool {
115         self.start() == self.end()
116     }
117 }
118
119 impl ops::Index<TextRange> for str {
120     type Output = str;
121
122     fn index(&self, index: TextRange) -> &str {
123         &self[index.start().0 as usize..index.end().0 as usize]
124     }
125 }