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