1use core::fmt;
8use core::ops;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
18pub struct TextSize(u32);
19
20impl TextSize {
21 pub const fn new(raw: u32) -> Self {
23 Self(raw)
24 }
25
26 pub const fn raw(self) -> u32 {
28 self.0
29 }
30}
31
32impl From<u32> for TextSize {
33 fn from(raw: u32) -> Self {
34 Self(raw)
35 }
36}
37
38impl From<TextSize> for u32 {
39 fn from(size: TextSize) -> Self {
40 size.0
41 }
42}
43
44impl From<TextSize> for usize {
45 fn from(size: TextSize) -> Self {
46 size.0 as usize
47 }
48}
49
50impl From<usize> for TextSize {
51 fn from(raw: usize) -> Self {
52 Self(raw as u32)
53 }
54}
55
56impl ops::Add for TextSize {
57 type Output = Self;
58 fn add(self, rhs: Self) -> Self {
59 Self(self.0 + rhs.0)
60 }
61}
62
63impl ops::Sub for TextSize {
64 type Output = Self;
65 fn sub(self, rhs: Self) -> Self {
66 Self(self.0 - rhs.0)
67 }
68}
69
70impl fmt::Display for TextSize {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 self.0.fmt(f)
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
84pub struct TextRange {
85 start: TextSize,
86 end: TextSize,
87}
88
89impl TextRange {
90 pub const fn new(start: TextSize, end: TextSize) -> Self {
92 Self { start, end }
93 }
94
95 pub const fn start(self) -> TextSize {
97 self.start
98 }
99
100 pub const fn end(self) -> TextSize {
102 self.end
103 }
104
105 pub const fn len(self) -> TextSize {
107 TextSize::new(self.end.0 - self.start.0)
108 }
109
110 pub const fn is_empty(self) -> bool {
112 self.start.0 == self.end.0
113 }
114
115 pub const fn contains(self, offset: TextSize) -> bool {
117 self.start.0 <= offset.0 && offset.0 < self.end.0
118 }
119
120 pub const fn from_offset_len(offset: usize, len: usize) -> Self {
122 Self {
123 start: TextSize::new(offset as u32),
124 end: TextSize::new((offset + len) as u32),
125 }
126 }
127
128 pub fn source_text<'a>(&self, source: &'a str) -> &'a str {
132 let start = self.start.0 as usize;
133 let end = self.end.0 as usize;
134 if start <= end && end <= source.len() {
135 &source[start..end]
136 } else {
137 ""
138 }
139 }
140
141 pub fn extend(&mut self, other: TextRange) {
143 self.end = other.end;
144 }
145}
146
147impl fmt::Display for TextRange {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 write!(f, "{}..{}", self.start, self.end)
150 }
151}