1use std::iter::Peekable;
27use std::str::Chars;
28
29use crate::{internal_error_map, error::*};
30
31pub(crate) struct ConfTokenizer<'token>
32{
33 srcmsg: &'token str,
34 chars: Peekable<Chars<'token>>,
35 pos: usize,
36 curchar: Option<char>,
37}
38
39impl<'token> ConfTokenizer<'token>
40{
41 pub fn from_str(text_buf: &'token str) -> CDnsResult<Self>
42 {
43 let mut chars: Peekable<Chars> = text_buf.chars().peekable();
44
45 let cur: Option<char> =
46 Some(chars.next().ok_or_else(|| internal_error_map!(CDnsErrorType::InternalError, "unexpected EOF"))?);
47
48
49 return Ok(
50 Self
51 {
52 srcmsg: text_buf,
53 chars: chars,
54 pos: 0,
55 curchar: cur,
56 }
57 );
58 }
59
60 #[inline]
61 fn move_next(&mut self)
62 {
63 self.pos += 1;
64
65 self.curchar = self.chars.next();
66 }
67
68 #[inline]
69 fn get_cur_char(&self) -> Option<char>
70 {
71 return self.curchar;
72 }
73
74 #[inline]
75 fn foresee_char(&mut self) -> Option<char>
76 {
77 return match self.chars.peek()
78 {
79 Some(c) => Some(*c),
80 None => None
81 };
82 }
83
84 #[inline]
85 fn is_eof(&mut self) -> bool
86 {
87 return self.curchar.is_none();
88 }
89
90 pub fn skip_upto_eol(&mut self)
91 {
92 while let Some(c) = self.get_cur_char()
93 {
94 if c == '\n'
95 {
96 self.move_next();
97 break; }
99
100 self.move_next();
101 }
102 }
103
104 pub
107 fn read_upto_eol(&mut self) -> CDnsResult<Vec<String>>
108 {
109 let mut params: Vec<String> = Vec::new();
110
111 while let Some(c) = self.get_cur_char()
112 {
113 if c == '\n'
114 {
115 self.move_next();
116 break; }
118 else if c.is_whitespace() == true
119 {
120 self.move_next();
122 continue;
123 }
124
125 let initpos = self.pos;
126
127 loop
128 {
129 match self.get_cur_char()
130 {
131 None => break,
132 Some(ref c) if c.is_whitespace() == true =>
133 {
134 break;
135 },
136 Some(ref c) if c.is_control() == true =>
137 {
138 self.move_next();
139 break;
140 },
141 Some(_c) =>
142 {
143 self.move_next();
144 }
145 }
146 }
147
148 params.push(self.srcmsg[initpos..self.pos].to_string());
149
150 }
151
152 return Ok(params);
153 }
154
155 pub
157 fn read_next(&mut self) -> CDnsResult<Option<&str>>
158 {
159 loop
160 {
161 while self.is_eof() == false && self.get_cur_char().unwrap().is_whitespace() == true
163 {
164 self.move_next();
165 }
166
167 if self.is_eof() == true
168 {
169 return Ok(None);
170 }
171
172 if self.get_cur_char().unwrap() == '#'
173 {
174 self.move_next();
175
176 while let Some(c) = self.get_cur_char()
177 {
178 if c == '\n'
179 {
180 self.move_next();
181 break; }
183
184 self.move_next();
185 }
186 }
187 else
188 {
189 break;
191 }
192 }
193
194 let initpos = self.pos;
195
196 loop
197 {
198 match self.get_cur_char()
199 {
200 None => break,
201 Some(ref c) if c.is_whitespace() == true =>
202 {
203 break;
204 },
205 Some(ref c) if c.is_control() == true =>
206 {
207 self.move_next();
208 break;
209 },
210 Some(_c) =>
211 {
212 self.move_next();
213 }
214 }
215 }
216
217 let ret = &self.srcmsg[initpos..self.pos];
218
219 return Ok(Some(ret));
220 }
221}