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}