jsdoc/
input.rs

1use std::{
2    ops::{Deref, Range, RangeFrom, RangeTo},
3    str::{CharIndices, Chars},
4};
5
6use nom::{
7    Compare, CompareResult, InputIter, InputLength, InputTake, Needed, Slice, UnspecializedInput,
8};
9use swc_common::{comments::Comment, BytePos, Span};
10
11use crate::ast::Text;
12
13#[derive(Debug, Clone, Copy)]
14pub struct Input<'i> {
15    start: BytePos,
16    end: BytePos,
17    src: &'i str,
18}
19
20impl<'a> From<&'a Comment> for Input<'a> {
21    fn from(c: &'a Comment) -> Self {
22        Self::new(c.span.lo, c.span.hi, &c.text)
23    }
24}
25
26impl<'i> Input<'i> {
27    pub const fn empty() -> Self {
28        Self::new(BytePos::DUMMY, BytePos::DUMMY, "")
29    }
30
31    pub const fn new(start: BytePos, end: BytePos, src: &'i str) -> Self {
32        Self { start, end, src }
33    }
34
35    #[inline(always)]
36    pub fn span(self) -> Span {
37        Span::new(self.start, self.end)
38    }
39}
40
41macro_rules! impl_slice {
42    ($T:ident) => {
43        impl Slice<$T<usize>> for Input<'_> {
44            fn slice(&self, range: $T<usize>) -> Self {
45                let s = self.src.slice(range);
46
47                Self::new(self.start, self.start + BytePos(s.as_bytes().len() as _), s)
48            }
49        }
50    };
51}
52
53impl_slice!(Range);
54impl_slice!(RangeFrom);
55impl_slice!(RangeTo);
56
57impl From<Input<'_>> for Text {
58    fn from(i: Input) -> Self {
59        Self {
60            span: Span::new(i.start, i.end),
61            value: i.src.into(),
62        }
63    }
64}
65
66impl InputTake for Input<'_> {
67    fn take(&self, count: usize) -> Self {
68        self.slice(..count)
69    }
70
71    fn take_split(&self, count: usize) -> (Self, Self) {
72        (self.slice(..count), self.slice(count..))
73    }
74}
75
76impl<'a> Compare<&'a str> for Input<'_> {
77    fn compare(&self, t: &'a str) -> CompareResult {
78        self.src.compare(t)
79    }
80
81    fn compare_no_case(&self, t: &'a str) -> CompareResult {
82        self.src.compare_no_case(t)
83    }
84}
85
86impl InputLength for Input<'_> {
87    fn input_len(&self) -> usize {
88        self.src.len()
89    }
90}
91
92impl UnspecializedInput for Input<'_> {}
93
94impl<'a> InputIter for Input<'a> {
95    type Item = char;
96    type Iter = CharIndices<'a>;
97    type IterElem = Chars<'a>;
98
99    fn iter_indices(&self) -> Self::Iter {
100        self.src.iter_indices()
101    }
102
103    fn iter_elements(&self) -> Self::IterElem {
104        self.src.iter_elements()
105    }
106
107    fn position<P>(&self, predicate: P) -> Option<usize>
108    where
109        P: Fn(Self::Item) -> bool,
110    {
111        self.src.position(predicate)
112    }
113
114    fn slice_index(&self, count: usize) -> Result<usize, Needed> {
115        self.src.slice_index(count)
116    }
117}
118
119impl Deref for Input<'_> {
120    type Target = str;
121
122    fn deref(&self) -> &Self::Target {
123        self.src
124    }
125}