1use alloc::string::String;
2
3use peek_nth::PeekableNth;
4
5use super::{Line, Lines, State};
6
7pub trait Input {
8 fn peek(&mut self, state: &State, offset: usize) -> Option<char>;
9 fn lines<'a>(&'a mut self, state: &'a mut State) -> Lines<'a>;
10
11 #[inline]
12 fn read(&mut self, state: &mut State) -> Option<char> {
13 match self.peek(state, 0) {
14 Some(ch) => {
15 state.read(ch == '\n');
16 Some(ch)
17 }
18 None => None,
19 }
20 }
21
22 #[inline]
23 fn read_offset(&mut self, state: &mut State, offset: usize) -> usize {
24 let mut read = 0;
25
26 for _ in 0..offset {
27 if self.read(state).is_none() {
28 break;
29 } else {
30 read += 1;
31 }
32 }
33
34 read
35 }
36
37 #[inline]
38 fn skip_line(&mut self, state: &mut State) {
39 if !self.is_done(state) {
40 while let Some(ch) = self.read(state) {
41 if ch == '\n' {
42 break;
43 }
44 }
45 }
46 }
47 #[inline]
48 fn peek_line(&mut self, state: &State) -> Option<Line> {
49 if self.is_done(state) {
50 None
51 } else {
52 let mut string = String::new();
53 let mut index = 0;
54 let offset = state.index();
55
56 while let Some(ch) = self.peek(state, index) {
57 if ch != '\n' {
58 index += 1;
59 string.push(ch);
60 } else {
61 break;
62 }
63 }
64
65 Some((offset, string).into())
66 }
67 }
68 #[inline]
69 fn read_line(&mut self, state: &mut State) -> Option<Line> {
70 if self.is_done(state) {
71 None
72 } else {
73 let mut string = String::new();
74 let offset = state.index();
75
76 while let Some(ch) = self.read(state) {
77 if ch != '\n' {
78 string.push(ch);
79 } else {
80 break;
81 }
82 }
83
84 Some((offset, string).into())
85 }
86 }
87
88 #[inline]
89 fn read_whitespace(&mut self, state: &mut State) -> Option<String> {
90 if self.is_done(state) {
91 None
92 } else {
93 let mut string = String::new();
94
95 while let Some(ch) = self.peek(state, 0) {
96 if ch.is_whitespace() {
97 self.read(state);
98 string.push(ch);
99 } else {
100 break;
101 }
102 }
103
104 if string.is_empty() {
105 None
106 } else {
107 Some(string)
108 }
109 }
110 }
111
112 #[inline]
113 fn skip_whitespaces(&mut self, state: &mut State) {
114 if !self.is_done(state) {
115 while let Some(ch) = self.peek(state, 0) {
116 if ch.is_whitespace() {
117 self.read(state);
118 }
119 }
120 }
121 }
122
123 #[inline]
124 fn is_done(&mut self, state: &State) -> bool {
125 !self.can_peek(state, 0)
126 }
127
128 #[inline]
129 fn can_peek(&mut self, state: &State, offset: usize) -> bool {
130 self.peek(state, offset).is_some()
131 }
132}
133
134impl<I> Input for PeekableNth<I>
135where
136 I: Iterator<Item = char>,
137{
138 #[inline]
139 fn peek(&mut self, state: &State, offset: usize) -> Option<char> {
140 self.peek_nth(state.index() + offset).map(Clone::clone)
141 }
142 #[inline]
143 fn lines<'a>(&'a mut self, state: &'a mut State) -> Lines<'a> {
144 Lines::new(self, state)
145 }
146}