srcpos/
lib.rs

1#[cfg(test)]
2mod tests;
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use core::clone::Clone;
8use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
9use core::convert::{From, Into};
10use core::default::Default;
11use core::fmt;
12use core::fmt::{Debug, Display};
13use core::hash::Hash;
14use core::marker::Copy;
15use core::ops::{Range, RangeFrom, RangeTo};
16
17/// Posation in source code
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19#[derive(PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
20pub struct Pos {
21    /// nth of line
22    pub line: usize,
23    /// nth of characters in current line
24    pub column: usize,
25}
26impl Pos {
27    /// New zero
28    #[inline]
29    pub const fn zero() -> Self {
30        Self::new_same(0)
31    }
32    /// New at
33    #[inline]
34    pub const fn new(line: usize, column: usize) -> Self {
35        Self { line, column }
36    }
37    /// New same value
38    #[inline]
39    pub const fn new_same(value: usize) -> Self {
40        Self::new(value, value)
41    }
42}
43
44impl Display for Pos {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "at {}:{}", self.line, self.column)
47    }
48}
49
50impl Debug for Pos {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "{{ at {}:{} }}", self.line, self.column)
53    }
54}
55
56impl Default for Pos {
57    #[inline(always)]
58    fn default() -> Self {
59        Self::zero()
60    }
61}
62
63impl From<(usize, usize)> for Pos {
64    #[inline]
65    fn from((line, column): (usize, usize)) -> Self {
66        Self::new(line, column)
67    }
68}
69impl From<[usize; 2]> for Pos {
70    #[inline]
71    fn from([line, column]: [usize; 2]) -> Self {
72        Self::new(line, column)
73    }
74}
75impl Into<(usize, usize)> for Pos {
76    #[inline]
77    fn into(self) -> (usize, usize) {
78        (self.line, self.column)
79    }
80}
81impl Into<[usize; 2]> for Pos {
82    #[inline]
83    fn into(self) -> [usize; 2] {
84        [self.line, self.column]
85    }
86}
87impl From<usize> for Pos {
88    #[inline]
89    fn from(value: usize) -> Self {
90        Self::new_same(value)
91    }
92}
93impl Into<usize> for Pos {
94    #[inline]
95    fn into(self) -> usize {
96        self.line
97    }
98}
99impl From<[usize; 1]> for Pos {
100    #[inline]
101    fn from([value]: [usize; 1]) -> Self {
102        Self::new_same(value)
103    }
104}
105impl Into<[usize; 1]> for Pos {
106    #[inline]
107    fn into(self) -> [usize; 1] {
108        [self.line]
109    }
110}
111impl From<()> for Pos {
112    #[inline]
113    fn from(_: ()) -> Self {
114        Self::zero()
115    }
116}
117impl<T> From<[T; 0]> for Pos {
118    #[inline]
119    fn from(_: [T; 0]) -> Self {
120        Self::zero()
121    }
122}
123
124/// Shorthand for Pos::new
125pub const fn pos(line: usize, column: usize) -> Pos {
126    Pos::new(line, column)
127}
128
129/// Build Pos
130/// # Examples
131/// ```
132/// # use srcpos::*;
133/// let a = posof!(1, 2);
134/// let b = posof!([1, 2]);
135/// let c = posof![1, 2];
136/// assert_eq!(a, b);
137/// assert_eq!(b, c);
138/// ```
139#[macro_export]
140macro_rules! posof {
141    ($a:expr, $b:expr) => {
142        $crate::pos($a, $b)
143    };
144    ($a:expr) => {
145        $crate::Pos::from($a)
146    };
147}
148
149//\/////////////////////////////////////////////////////////////////////////////////////////////////
150
151/// Range of Posation in source code
152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
153#[derive(PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
154pub struct Loc {
155    /// from
156    pub from: Pos,
157    /// to
158    pub to: Pos,
159}
160impl Loc {
161    /// New at
162    #[inline]
163    pub const fn new(from: Pos, to: Pos) -> Self {
164        Self { from, to }
165    }
166    /// New at
167    #[inline]
168    pub const fn new_at(
169        from_line: usize,
170        from_column: usize,
171        to_line: usize,
172        to_column: usize,
173    ) -> Self {
174        Self::new(
175            Pos::new(from_line, from_column),
176            Pos::new(to_line, to_column),
177        )
178    }
179    /// New zero
180    #[inline]
181    pub const fn zero() -> Self {
182        Self::new_same_pos(Pos::zero())
183    }
184    /// New same value
185    #[inline]
186    pub const fn new_same(value: usize) -> Self {
187        Self::new_same_pos(Pos::new_same(value))
188    }
189    /// New same value
190    #[inline]
191    pub const fn new_same_pos(pos: Pos) -> Self {
192        Self::new(pos, pos)
193    }
194}
195
196impl Display for Loc {
197    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198        write!(
199            f,
200            "at {}:{} to {}:{}",
201            self.from.line, self.from.column, self.to.line, self.to.column,
202        )
203    }
204}
205
206impl Debug for Loc {
207    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208        write!(
209            f,
210            "{{ at {}:{} to {}:{} }}",
211            self.from.line, self.from.column, self.to.line, self.to.column,
212        )
213    }
214}
215
216impl Default for Loc {
217    #[inline(always)]
218    fn default() -> Self {
219        Self::zero()
220    }
221}
222
223// #region From Into Basic Misc
224impl From<(usize, usize, usize, usize)> for Loc {
225    #[inline]
226    fn from((a1, b1, a2, b2): (usize, usize, usize, usize)) -> Self {
227        Self::new_at(a1, b1, a2, b2)
228    }
229}
230impl Into<(usize, usize, usize, usize)> for Loc {
231    #[inline]
232    fn into(self) -> (usize, usize, usize, usize) {
233        (
234            self.from.line,
235            self.from.column,
236            self.to.line,
237            self.to.column,
238        )
239    }
240}
241impl From<[usize; 4]> for Loc {
242    #[inline]
243    fn from([a1, b1, a2, b2]: [usize; 4]) -> Self {
244        Self::new_at(a1, b1, a2, b2)
245    }
246}
247impl Into<[usize; 4]> for Loc {
248    fn into(self) -> [usize; 4] {
249        [
250            self.from.line,
251            self.from.column,
252            self.to.line,
253            self.to.column,
254        ]
255    }
256}
257impl Into<[[usize; 2]; 2]> for Loc {
258    #[inline]
259    fn into(self) -> [[usize; 2]; 2] {
260        [
261            [self.from.line, self.from.column],
262            [self.to.line, self.to.column],
263        ]
264    }
265}
266impl Into<[(usize, usize); 2]> for Loc {
267    #[inline]
268    fn into(self) -> [(usize, usize); 2] {
269        [
270            (self.from.line, self.from.column),
271            (self.to.line, self.to.column),
272        ]
273    }
274}
275impl Into<[usize; 2]> for Loc {
276    #[inline]
277    fn into(self) -> [usize; 2] {
278        [self.from.line, self.from.column]
279    }
280}
281impl From<usize> for Loc {
282    #[inline]
283    fn from(value: usize) -> Self {
284        Self::new_same(value)
285    }
286}
287impl Into<usize> for Loc {
288    #[inline]
289    fn into(self) -> usize {
290        self.from.line
291    }
292}
293impl Into<[usize; 1]> for Loc {
294    #[inline]
295    fn into(self) -> [usize; 1] {
296        [self.from.line]
297    }
298}
299impl From<()> for Loc {
300    #[inline]
301    fn from(_: ()) -> Self {
302        Self::zero()
303    }
304}
305impl<T> From<[T; 0]> for Loc {
306    #[inline]
307    fn from(_: [T; 0]) -> Self {
308        Self::zero()
309    }
310}
311// #endregion
312
313// #region From Into Range
314impl<T: Into<Pos>> From<Range<T>> for Loc {
315    #[inline]
316    fn from(r: Range<T>) -> Self {
317        Self::new(r.start.into(), r.end.into())
318    }
319}
320impl<T: From<Pos>> Into<Range<T>> for Loc {
321    #[inline]
322    fn into(self) -> Range<T> {
323        self.from.into()..self.to.into()
324    }
325}
326impl<T: Into<Pos>> From<RangeTo<T>> for Loc {
327    #[inline]
328    fn from(r: RangeTo<T>) -> Self {
329        Self::new(Pos::zero(), r.end.into())
330    }
331}
332impl<T: From<Pos>> Into<RangeTo<T>> for Loc {
333    #[inline]
334    fn into(self) -> RangeTo<T> {
335        ..self.to.into()
336    }
337}
338impl<T: From<Pos>> Into<RangeFrom<T>> for Loc {
339    #[inline]
340    fn into(self) -> RangeFrom<T> {
341        self.from.into()..
342    }
343}
344// #endregion
345
346// #region From Into Misc
347impl<T: Into<Pos>> From<(T, T)> for Loc {
348    #[inline]
349    fn from((from, to): (T, T)) -> Self {
350        Self::new(from.into(), to.into())
351    }
352}
353impl<T: From<Pos>> Into<(T, T)> for Loc {
354    #[inline]
355    fn into(self) -> (T, T) {
356        (self.from.into(), self.to.into())
357    }
358}
359impl<T: Into<Pos>> From<[T; 2]> for Loc {
360    #[inline]
361    fn from([from, to]: [T; 2]) -> Self {
362        Self::new(from.into(), to.into())
363    }
364}
365impl<T: From<Pos>> Into<[T; 2]> for Loc {
366    #[inline]
367    fn into(self) -> [T; 2] {
368        [self.from.into(), self.to.into()]
369    }
370}
371impl From<Pos> for Loc {
372    #[inline]
373    fn from(pos: Pos) -> Self {
374        Self::new_same_pos(pos)
375    }
376}
377impl Into<Pos> for Loc {
378    #[inline]
379    fn into(self) -> Pos {
380        self.from
381    }
382}
383impl<T: Into<Pos>> From<[T; 1]> for Loc {
384    #[inline]
385    fn from([pos]: [T; 1]) -> Self {
386        Self::new_same_pos(pos.into())
387    }
388}
389impl<T: From<Pos>> Into<[T; 1]> for Loc {
390    #[inline]
391    fn into(self) -> [T; 1] {
392        [self.from.into()]
393    }
394}
395// #endregion
396
397/// Shorthand for Loc::new
398#[inline]
399pub const fn loc(from: Pos, to: Pos) -> Loc {
400    Loc::new(from, to)
401}
402
403/// Build Loc  
404/// # Examples
405/// ```
406/// # use srcpos::*;
407/// let a = locof!(pos(1, 2), pos(3, 4));
408/// let b = locof!([1, 2], [3, 4]);
409/// let c = locof!(1, 2, 3, 4);
410/// let d = locof!(pos(1, 2)..pos(3, 4));
411/// let e = locof![1, 2, 3, 4];
412/// assert_eq!(a, b);
413/// assert_eq!(b, c);
414/// assert_eq!(c, d);
415/// assert_eq!(d, e);
416/// ```
417#[macro_export]
418macro_rules! locof {
419    ($from:expr, $to:expr) => {
420        $crate::loc($from.into(), $to.into())
421    };
422    ($a:expr, $b:expr, $c:expr, $d:expr) => {
423        $crate::loc(pos($a, $b), pos($c, $d))
424    };
425    ($v:expr) => {
426        $crate::Loc::from($v)
427    };
428}
429
430//\/////////////////////////////////////////////////////////////////////////////////////////////////
431
432/// Expands to the pos on which it was invoked.
433/// ## See
434/// - [`line!`](https://doc.rust-lang.org/std/macro.line.html)
435/// - [`column!`](https://doc.rust-lang.org/std/macro.column.html)
436/// # Examples
437/// ```rust
438/// # use srcpos::*;
439/// let current_pos = pos!();
440/// println!("defined on pos: {}", current_pos);
441/// ```
442#[macro_export]
443macro_rules! pos {
444    () => {
445        $crate::pos(line!() as usize, column!() as usize)
446    };
447}