source_tools/
source_cursor.rs1use crate::{Cursor, SourceToken, Span, ToSpan};
2
3#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct SourceCursor<'a, T> {
6 cursor: Cursor<T>,
7 source: &'a str,
8}
9
10impl<'a, T> SourceCursor<'a, T> {
11 #[inline(always)]
13 pub const fn new(cursor: Cursor<T>, source: &'a str) -> Self {
14 Self { cursor, source }
15 }
16
17 #[inline(always)]
19 pub const fn cursor_ref(&self) -> &Cursor<T> {
20 &self.cursor
21 }
22
23 #[inline(always)]
25 pub const fn source(&self) -> &'a str {
26 self.source
27 }
28}
29
30impl<'a, T: Copy> SourceCursor<'a, T> {
31 #[inline(always)]
33 pub const fn cursor(&self) -> Cursor<T> {
34 self.cursor
35 }
36
37 #[inline(always)]
39 pub const fn token(&self) -> T {
40 self.cursor.token()
41 }
42}
43
44impl<'a, T: SourceToken> SourceCursor<'a, T> {
45 #[inline(always)]
47 pub fn from(cursor: Cursor<T>, source: &'a str) -> Self {
48 debug_assert_eq!(cursor.len() as usize, source.len(), "source length must match cursor length");
49 Self::new(cursor, source)
50 }
51
52 pub fn value(&self) -> &'a str {
54 let leading = self.token().leading_len() as usize;
55 let trailing = self.token().trailing_len() as usize;
56 &self.source[leading..self.source.len() - trailing]
57 }
58}
59
60impl<T: SourceToken> ToSpan for SourceCursor<'_, T> {
61 fn to_span(&self) -> Span {
62 self.cursor.to_span()
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::SourceOffset;
70
71 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
72 struct Token(u32);
73
74 impl SourceToken for Token {
75 type Kind = ();
76 const EMPTY: Self = Token(0);
77
78 fn kind(self) -> Self::Kind {}
79
80 fn len(self) -> u32 {
81 self.0
82 }
83
84 fn kind_name(self) -> &'static str {
85 "test"
86 }
87 }
88
89 #[test]
90 fn binds_cursor_to_source() {
91 let cursor = Cursor::new(SourceOffset(2), Token(3));
92 let sourced = SourceCursor::from(cursor, "abc");
93 assert_eq!(sourced.cursor(), cursor);
94 assert_eq!(sourced.source(), "abc");
95 assert_eq!(sourced.to_span(), Span::new(SourceOffset(2), SourceOffset(5)));
96 }
97}