nom_grapheme_clusters/
source.rs1mod indexing;
4
5#[cfg(test)]
6mod test;
7
8use crate::{location::Location, span::Span};
9pub use indexing::SourceIndex;
10use indexing::{IndexArray, IndexArrayBuilder, IndexArrayIter};
11use std::{
12 cmp::Ordering,
13 fmt,
14 hash::{Hash, Hasher},
15 ops::Index,
16 sync::Arc,
17};
18use unicode_segmentation::UnicodeSegmentation;
19
20#[doc(hidden)]
21pub fn count_grapheme_clusters(input: &str) -> usize {
22 input.graphemes(true).count()
23}
24
25#[derive(Debug)]
27struct SourceInner {
28 name: Box<str>,
30 contents: Box<str>,
32 segments: IndexArray,
34 newlines: IndexArray,
36}
37
38#[derive(Debug, Clone)]
42pub struct Source {
43 inner: Arc<SourceInner>,
45}
46
47impl Source {
48 pub fn new<S0, S1>(name: S0, contents: S1) -> Self
52 where
53 S0: Into<Box<str>>,
54 S1: Into<Box<str>>,
55 {
56 let name = name.into();
57 let contents = contents.into();
58 let mut segments = IndexArrayBuilder::new();
59 let mut newlines = IndexArrayBuilder::new();
60
61 for (idx, grapheme) in contents.grapheme_indices(true) {
62 if grapheme == "\n" {
63 newlines.push(segments.len());
64 }
65 segments.push(idx);
66 }
67 segments.push(contents.len());
68
69 let segments = segments.into();
70 let newlines = newlines.into();
71 let inner = SourceInner { name, contents, segments, newlines };
72 Self { inner: Arc::new(inner) }
73 }
74
75 pub fn name(&self) -> &str {
77 &self.inner.name
78 }
79
80 pub fn len(&self) -> usize {
82 self.inner.segments.len() - 1
83 }
84
85 pub fn contents(&self) -> &str {
87 &self.inner.contents
88 }
89
90 pub fn seg_byte_indices(&self) -> SegmentByteIndices {
93 SegmentByteIndices { inner: self.inner.segments.iter() }
94 }
95
96 pub fn newline_indices(&self) -> NewlineIndices {
99 NewlineIndices { inner: self.inner.segments.iter() }
100 }
101
102 pub(super) fn line(&self, position: usize) -> usize {
105 match self.inner.newlines.binary_search(position) {
106 Ok(n) | Err(n) => n,
107 }
108 }
109
110 pub(super) fn line_start(&self, line: usize) -> usize {
116 if line == 0 {
117 0
118 } else {
119 self.inner.newlines.index(line - 1) + 1
120 }
121 }
122
123 pub(super) fn try_line_start(&self, line: usize) -> Option<usize> {
126 if line == 0 {
127 Some(0)
128 } else {
129 self.inner.newlines.get(line - 1).map(|position| position + 1)
130 }
131 }
132
133 pub fn get<I>(&self, indexer: I) -> Option<&I::Output>
136 where
137 I: SourceIndex,
138 {
139 indexer.get(self)
140 }
141
142 pub fn full_span(&self) -> Span {
144 let start = Location::new_unchecked(self.clone(), 0);
145 Span::new_unchecked(start, self.len())
146 }
147}
148
149impl<I> Index<I> for Source
150where
151 I: SourceIndex,
152{
153 type Output = I::Output;
154
155 fn index(&self, indexer: I) -> &Self::Output {
156 indexer.index(self)
157 }
158}
159
160impl PartialEq for Source {
161 fn eq(&self, other: &Self) -> bool {
162 Arc::ptr_eq(&self.inner, &other.inner)
163 }
164}
165
166impl Eq for Source {}
167
168impl PartialOrd for Source {
169 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
170 Some(self.cmp(other))
171 }
172}
173
174impl Ord for Source {
175 fn cmp(&self, other: &Self) -> Ordering {
176 (&*self.inner as *const SourceInner).cmp(&(&*other.inner as *const _))
177 }
178}
179
180impl Hash for Source {
181 fn hash<H>(&self, hasher: &mut H)
182 where
183 H: Hasher,
184 {
185 (&*self.inner as *const SourceInner).hash(hasher)
186 }
187}
188
189impl fmt::Display for Source {
190 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
191 fmtr.write_str(self.name())
192 }
193}
194
195#[derive(Debug)]
198pub struct SegmentByteIndices<'src> {
199 inner: IndexArrayIter<'src>,
201}
202
203impl<'src> Iterator for SegmentByteIndices<'src> {
204 type Item = usize;
205
206 fn next(&mut self) -> Option<Self::Item> {
207 self.inner.next()
208 }
209
210 fn size_hint(&self) -> (usize, Option<usize>) {
211 let len = self.inner.len();
212 (len, Some(len))
213 }
214}
215
216impl<'src> DoubleEndedIterator for SegmentByteIndices<'src> {
217 fn next_back(&mut self) -> Option<Self::Item> {
218 self.inner.next_back()
219 }
220}
221
222impl<'array> ExactSizeIterator for SegmentByteIndices<'array> {}
223
224#[derive(Debug)]
227pub struct NewlineIndices<'src> {
228 inner: IndexArrayIter<'src>,
230}
231
232impl<'src> Iterator for NewlineIndices<'src> {
233 type Item = usize;
234
235 fn next(&mut self) -> Option<Self::Item> {
236 self.inner.next()
237 }
238
239 fn size_hint(&self) -> (usize, Option<usize>) {
240 let len = self.inner.len();
241 (len, Some(len))
242 }
243}
244
245impl<'src> DoubleEndedIterator for NewlineIndices<'src> {
246 fn next_back(&mut self) -> Option<Self::Item> {
247 self.inner.next_back()
248 }
249}
250
251impl<'array> ExactSizeIterator for NewlineIndices<'array> {}