rls_span/
lib.rs

1#![cfg_attr(feature = "nightly", feature(step_trait, trusted_step))]
2
3use std::marker::PhantomData;
4use std::path::PathBuf;
5
6#[cfg(feature = "nightly")]
7use std::iter::Step;
8
9use serde::{Deserialize, Serialize};
10
11pub mod compiler;
12
13#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
14pub struct Column<I: Indexed>(pub u32, PhantomData<I>);
15
16impl<I: Indexed> Column<I> {
17    fn new(c: u32) -> Column<I> {
18        Column(c, PhantomData)
19    }
20}
21
22impl<I: Indexed> Clone for Column<I> {
23    fn clone(&self) -> Column<I> {
24        *self
25    }
26}
27
28impl<I: Indexed> Copy for Column<I> {}
29
30impl<I: Indexed> Serialize for Column<I> {
31    fn serialize<S: serde::Serializer>(
32        &self,
33        s: S,
34    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error> {
35        s.serialize_u32(self.0)
36    }
37}
38
39impl<'dt, I: Indexed> Deserialize<'dt> for Column<I> {
40    fn deserialize<D: serde::Deserializer<'dt>>(
41        d: D,
42    ) -> std::result::Result<Self, <D as serde::Deserializer<'dt>>::Error> {
43        <u32 as Deserialize>::deserialize(d).map(Column::new)
44    }
45}
46
47#[cfg(feature = "serialize-rustc")]
48impl<I: Indexed> rustc_serialize::Decodable for Column<I> {
49    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Column<I>, D::Error> {
50        d.read_u32().map(Column::new)
51    }
52}
53
54#[cfg(feature = "serialize-rustc")]
55impl<I: Indexed> rustc_serialize::Encodable for Column<I> {
56    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
57        s.emit_u32(self.0)
58    }
59}
60
61impl Column<OneIndexed> {
62    pub fn new_one_indexed(c: u32) -> Column<OneIndexed> {
63        Column(c, PhantomData)
64    }
65
66    pub fn zero_indexed(self) -> Column<ZeroIndexed> {
67        Column(self.0 - 1, PhantomData)
68    }
69}
70
71impl Column<ZeroIndexed> {
72    pub fn new_zero_indexed(c: u32) -> Column<ZeroIndexed> {
73        Column(c, PhantomData)
74    }
75
76    pub fn one_indexed(self) -> Column<OneIndexed> {
77        Column(self.0 + 1, PhantomData)
78    }
79}
80
81#[cfg(feature = "nightly")]
82macro_rules! impl_step {
83    ($target: ty) => {
84        impl Step for $target {
85            fn steps_between(start: &Self, end: &Self) -> Option<usize> {
86                Step::steps_between(&start.0, &end.0)
87            }
88            fn forward_checked(arg: Self, count: usize) -> Option<Self> {
89                Step::forward_checked(arg.0, count).map(|x| Self(x, PhantomData))
90            }
91            fn backward_checked(arg: Self, count: usize) -> Option<Self> {
92                Step::backward_checked(arg.0, count).map(|x| Self(x, PhantomData))
93            }
94        }
95        unsafe impl TrustedStep for $target {}
96    };
97}
98
99#[cfg(feature = "nightly")]
100impl_step!(Column<ZeroIndexed>);
101#[cfg(feature = "nightly")]
102impl_step!(Column<OneIndexed>);
103#[cfg(feature = "nightly")]
104impl_step!(Row<ZeroIndexed>);
105#[cfg(feature = "nightly")]
106impl_step!(Row<OneIndexed>);
107
108#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
109pub struct Row<I: Indexed>(pub u32, PhantomData<I>);
110
111impl<I: Indexed> Row<I> {
112    fn new(c: u32) -> Row<I> {
113        Row(c, PhantomData)
114    }
115}
116
117impl<I: Indexed> Clone for Row<I> {
118    fn clone(&self) -> Row<I> {
119        *self
120    }
121}
122
123impl<I: Indexed> Copy for Row<I> {}
124
125impl<I: Indexed> serde::Serialize for Row<I> {
126    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
127        s.serialize_u32(self.0)
128    }
129}
130
131impl<'dt, I: Indexed> serde::Deserialize<'dt> for Row<I> {
132    fn deserialize<D: serde::Deserializer<'dt>>(d: D) -> std::result::Result<Self, D::Error> {
133        <u32 as Deserialize>::deserialize(d).map(Row::new)
134    }
135}
136
137#[cfg(feature = "serialize-rustc")]
138impl<I: Indexed> rustc_serialize::Decodable for Row<I> {
139    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Row<I>, D::Error> {
140        d.read_u32().map(Row::new)
141    }
142}
143
144#[cfg(feature = "serialize-rustc")]
145impl<I: Indexed> rustc_serialize::Encodable for Row<I> {
146    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
147        s.emit_u32(self.0)
148    }
149}
150
151impl Row<OneIndexed> {
152    pub fn new_one_indexed(c: u32) -> Row<OneIndexed> {
153        Row(c, PhantomData)
154    }
155
156    pub fn zero_indexed(self) -> Row<ZeroIndexed> {
157        Row(self.0 - 1, PhantomData)
158    }
159}
160
161impl Row<ZeroIndexed> {
162    pub fn new_zero_indexed(c: u32) -> Row<ZeroIndexed> {
163        Row(c, PhantomData)
164    }
165
166    pub fn one_indexed(self) -> Row<OneIndexed> {
167        Row(self.0 + 1, PhantomData)
168    }
169}
170
171#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
172#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
173#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
174pub struct Position<I: Indexed> {
175    pub row: Row<I>,
176    pub col: Column<I>,
177}
178
179impl<I: Indexed> Position<I> {
180    pub fn new(row: Row<I>, col: Column<I>) -> Position<I> {
181        Position { row, col }
182    }
183}
184
185impl<I: Indexed> Clone for Position<I> {
186    fn clone(&self) -> Position<I> {
187        *self
188    }
189}
190
191impl<I: Indexed> Copy for Position<I> {}
192
193impl Position<OneIndexed> {
194    pub fn zero_indexed(self) -> Position<ZeroIndexed> {
195        Position { row: self.row.zero_indexed(), col: self.col.zero_indexed() }
196    }
197}
198
199impl Position<ZeroIndexed> {
200    pub fn one_indexed(self) -> Position<OneIndexed> {
201        Position { row: self.row.one_indexed(), col: self.col.one_indexed() }
202    }
203}
204
205#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
206#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
207#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
208pub struct Range<I: Indexed> {
209    pub row_start: Row<I>,
210    pub row_end: Row<I>,
211    pub col_start: Column<I>,
212    pub col_end: Column<I>,
213}
214
215impl<I: Indexed> Range<I> {
216    pub fn new(
217        row_start: Row<I>,
218        row_end: Row<I>,
219        col_start: Column<I>,
220        col_end: Column<I>,
221    ) -> Range<I> {
222        Range { row_start, row_end, col_start, col_end }
223    }
224
225    pub fn from_positions(start: Position<I>, end: Position<I>) -> Range<I> {
226        Range { row_start: start.row, row_end: end.row, col_start: start.col, col_end: end.col }
227    }
228
229    pub fn start(self) -> Position<I> {
230        Position { row: self.row_start, col: self.col_start }
231    }
232
233    pub fn end(self) -> Position<I> {
234        Position { row: self.row_end, col: self.col_end }
235    }
236}
237
238impl<I: Indexed> Clone for Range<I> {
239    fn clone(&self) -> Range<I> {
240        *self
241    }
242}
243
244impl<I: Indexed> Copy for Range<I> {}
245
246impl Range<OneIndexed> {
247    pub fn zero_indexed(self) -> Range<ZeroIndexed> {
248        Range {
249            row_start: self.row_start.zero_indexed(),
250            row_end: self.row_end.zero_indexed(),
251            col_start: self.col_start.zero_indexed(),
252            col_end: self.col_end.zero_indexed(),
253        }
254    }
255}
256
257impl Range<ZeroIndexed> {
258    pub fn one_indexed(self) -> Range<OneIndexed> {
259        Range {
260            row_start: self.row_start.one_indexed(),
261            row_end: self.row_end.one_indexed(),
262            col_start: self.col_start.one_indexed(),
263            col_end: self.col_end.one_indexed(),
264        }
265    }
266}
267
268#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
269#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
270#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
271pub struct Location<I: Indexed> {
272    pub file: PathBuf,
273    pub position: Position<I>,
274}
275
276impl<I: Indexed> Location<I> {
277    pub fn new<F: Into<PathBuf>>(row: Row<I>, col: Column<I>, file: F) -> Location<I> {
278        Location { position: Position { row, col }, file: file.into() }
279    }
280
281    pub fn from_position<F: Into<PathBuf>>(position: Position<I>, file: F) -> Location<I> {
282        Location { position, file: file.into() }
283    }
284}
285
286impl<I: Indexed> Clone for Location<I> {
287    fn clone(&self) -> Location<I> {
288        Location { position: self.position, file: self.file.clone() }
289    }
290}
291
292impl Location<OneIndexed> {
293    pub fn zero_indexed(&self) -> Location<ZeroIndexed> {
294        Location { position: self.position.zero_indexed(), file: self.file.clone() }
295    }
296}
297
298impl Location<ZeroIndexed> {
299    pub fn one_indexed(&self) -> Location<OneIndexed> {
300        Location { position: self.position.one_indexed(), file: self.file.clone() }
301    }
302}
303
304#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
305#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
306#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
307pub struct Span<I: Indexed> {
308    pub file: PathBuf,
309    pub range: Range<I>,
310}
311
312impl<I: Indexed> Span<I> {
313    pub fn new<F: Into<PathBuf>>(
314        row_start: Row<I>,
315        row_end: Row<I>,
316        col_start: Column<I>,
317        col_end: Column<I>,
318        file: F,
319    ) -> Span<I> {
320        Span { range: Range { row_start, row_end, col_start, col_end }, file: file.into() }
321    }
322
323    pub fn from_range<F: Into<PathBuf>>(range: Range<I>, file: F) -> Span<I> {
324        Span { range, file: file.into() }
325    }
326
327    pub fn from_positions<F: Into<PathBuf>>(
328        start: Position<I>,
329        end: Position<I>,
330        file: F,
331    ) -> Span<I> {
332        Span { range: Range::from_positions(start, end), file: file.into() }
333    }
334}
335
336impl<I: Indexed> Clone for Span<I> {
337    fn clone(&self) -> Span<I> {
338        Span { range: self.range, file: self.file.clone() }
339    }
340}
341
342impl Span<OneIndexed> {
343    pub fn zero_indexed(&self) -> Span<ZeroIndexed> {
344        Span { range: self.range.zero_indexed(), file: self.file.clone() }
345    }
346}
347
348impl Span<ZeroIndexed> {
349    pub fn one_indexed(&self) -> Span<OneIndexed> {
350        Span { range: self.range.one_indexed(), file: self.file.clone() }
351    }
352}
353
354pub trait Indexed {}
355
356#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
357#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
358#[derive(Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
359pub struct ZeroIndexed;
360impl Indexed for ZeroIndexed {}
361
362#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
363#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
364#[derive(Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
365pub struct OneIndexed;
366impl Indexed for OneIndexed {}
367
368#[cfg(feature = "nightly")]
369#[cfg(test)]
370mod test {
371    use super::*;
372
373    #[test]
374    fn iter_row() {
375        assert_eq!((Row::new_one_indexed(4)..Row::new_one_indexed(8)).count(), 4);
376        assert_eq!(
377            &*(Row::new_zero_indexed(0)..=Row::new_zero_indexed(8))
378                .filter(|r| r.0 < 3)
379                .map(|r| r.0)
380                .collect::<Vec<_>>(),
381            &[0, 1, 2],
382        );
383    }
384}