1use crate::*;
2
3use std::cell::RefCell;
4use std::collections::VecDeque;
5use std::fmt::Debug;
6use std::io::{BufRead, Cursor, Read, Seek, SeekFrom};
7use std::ops::Deref;
8
9mod tilde_kinds;
10pub use tilde_kinds::*;
11
12mod reveal_impl;
13pub use reveal_impl::*;
14
15mod args;
16pub use args::*;
17
18mod tilde_able_impl;
19
20#[doc = r"The tilde struct"]
21#[derive(Debug, PartialEq, Clone)]
22pub struct Tilde {
23 len: usize,
24 value: TildeKind,
25}
26
27impl Tilde {
28 pub fn new(len: usize, value: TildeKind) -> Self {
29 Self { len, value }
30 }
31
32 pub fn len(&self) -> usize {
33 self.len
34 }
35
36 pub fn reveal(&self, arg: &dyn TildeAble, mut buf: &mut String) -> Result<(), TildeError> {
37 self.value.match_reveal(arg, &mut buf)?;
38 Ok(())
39 }
40
41 fn scan_for_kind(
49 c: &mut Cursor<&'_ str>,
50 ) -> Result<
51 Box<dyn for<'a, 'b> Fn(&'a mut std::io::Cursor<&'b str>) -> Result<Tilde, TildeError>>,
52 TildeError,
53 > {
54 let mut buf = [0u8; 1];
55 c.read(&mut buf)
56 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
57 if buf[0] != b'~' {
58 return Err(TildeError::new(ErrorKind::ParseError, "should start with ~").into());
59 }
60
61 let mut bucket = vec![b'~'];
62 let mut buf_offset = 1;
63 let mut escape = false;
64
65 loop {
66 if c.read(&mut buf)
67 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?
68 == 0
69 || buf[0] == 0_u8
70 {
71 return Err(TildeError::new(ErrorKind::ParseError, "read to end"));
72 }
73
74 buf_offset += 1;
75 bucket.extend_from_slice(&buf);
76 if !escape {
78 match &bucket[..] {
79 [.., b'\\'] => {
80 escape = true;
82 continue;
83 }
84 [.., b'a'] | [.., b'A'] => {
85 c.seek(SeekFrom::Current(-buf_offset))
86 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_value));
88 }
89 [.., b'@', b'{'] | [.., b'{'] => {
90 c.seek(SeekFrom::Current(-buf_offset))
91 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_loop));
93 }
94 [.., _, b'$'] | [.., b'$'] | [.., b'f' | b'F'] => {
95 c.seek(SeekFrom::Current(-buf_offset))
96 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_float));
98 }
99 [.., b'd'] | [.., b'D'] => {
100 c.seek(SeekFrom::Current(-buf_offset))
101 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_digit));
103 }
104 [.., b'#' | b':' | b'@', b'['] | [.., b'['] => {
105 c.seek(SeekFrom::Current(-buf_offset))
106 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_cond));
108 }
109 [.., b'^'] => {
110 c.seek(SeekFrom::Current(-buf_offset))
111 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_loop_end));
113 }
114 [.., b':', b'*'] | [.., b'*'] => {
115 c.seek(SeekFrom::Current(-buf_offset))
116 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_star));
118 }
119 [.., _, b'~'] => {
120 c.seek(SeekFrom::Current(-buf_offset))
122 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_tildes));
124 }
125 [.., b'S'] | [.., b's'] => {
126 c.seek(SeekFrom::Current(-buf_offset))
127 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_standard));
129 }
130 [.., b'@', b'c' | b'C'] | [.., b'C' | b'c'] => {
131 c.seek(SeekFrom::Current(-buf_offset))
132 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_char));
134 }
135 [.., b'R' | b'r'] => {
136 c.seek(SeekFrom::Current(-buf_offset))
137 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; return Ok(Box::new(Self::parse_radix));
139 }
140
141 [.., b'%'] => {
142 return Err(TildeError::new(
143 ErrorKind::ParseError,
144 "Unsupport the last symbol of '%', try to use \\n instead",
145 ));
146 }
147 _ => {}
148 }
149 }
150 escape = false;
151 }
152 }
153
154 pub fn parse(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
156 let parser = Self::scan_for_kind(c)?;
158 parser(c)
159 }
160
161 fn parse_loop(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
163 let mut char_buf = [0u8; 3]; c.read(&mut char_buf)
165 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
166
167 let mut loop_kind = TildeLoopKind::Nil;
168 let mut total_len = 0;
169 match char_buf {
170 [b'~', b'{', ..] => {
171 total_len += 2;
172 c.seek(SeekFrom::Current(-1))
173 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
174 }
175 [b'~', b'@', b'{'] => {
176 total_len += 3;
177 loop_kind = TildeLoopKind::At;
178 }
179
180 _ => {
181 c.seek(SeekFrom::Current(-3))
182 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
183 return Err(TildeError::new(
184 ErrorKind::ParseError,
185 "should start with ~{",
186 ));
187 }
188 }
189
190 let mut result = vec![];
191 let mut buf = vec![];
192 let mut char_buf = [0u8; 3];
193
194 loop {
195 c.read_until(b'~', &mut buf)
197 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
198
199 match buf.as_slice() {
200 [b'~'] => {
201 c.seek(SeekFrom::Current(-1))
202 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
203 }
204 [.., b'~'] => {
205 c.seek(SeekFrom::Current(-1))
206 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
207 result.push(Tilde::new(
208 buf.len() - 1,
209 TildeKind::Text(
210 String::from_utf8(buf[..buf.len() - 1].to_vec()).map_err(|e| {
211 TildeError::new(ErrorKind::ParseError, e.to_string())
212 })?,
213 ),
214 ));
215 total_len += buf.len() - 1;
216 }
217 [..] => {
218 result.push(Tilde::new(
219 buf.len() - 1,
220 TildeKind::Text(
221 String::from_utf8(buf[..buf.len() - 1].to_vec()).map_err(|e| {
222 TildeError::new(ErrorKind::ParseError, e.to_string())
223 })?,
224 ),
225 ));
226 total_len += buf.len();
227 return Ok(Tilde::new(total_len, TildeKind::Loop((result, loop_kind))));
228 }
229 }
230
231 c.read(&mut char_buf)
232 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
233
234 match char_buf {
235 [b'~', b'}', 0] => {
236 return Ok(Tilde::new(
237 total_len + 2,
238 TildeKind::Loop((result, loop_kind)),
239 ));
240 }
241 [b'~', b'}', ..] => {
242 c.seek(SeekFrom::Current(-1))
243 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
244 return Ok(Tilde::new(
245 total_len + 2,
246 TildeKind::Loop((result, loop_kind)),
247 ));
248 }
249 [b'~', b':', b'}'] => {
250 return Ok(Tilde::new(
251 total_len + 3,
252 TildeKind::Loop((
253 result,
254 if loop_kind == TildeLoopKind::Nil {
255 TildeLoopKind::NilColon
256 } else {
257 loop_kind
258 },
259 )),
260 ));
261 }
262 _ => {
263 let back = 3 - char_buf.iter().filter(|b| **b == 0).count() as i64;
264 c.seek(SeekFrom::Current(-back))
265 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
266 }
267 }
268
269 let next = Tilde::parse(c)?;
271 total_len += next.len;
272 result.push(next);
273 char_buf = [0; 3];
274 buf.clear()
275 }
276 }
277
278 fn parse_loop_end(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
280 let mut char_buf = [0u8; 2]; c.read(&mut char_buf)
282 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
283 if char_buf != *b"~^" {
284 c.seek(SeekFrom::Current(-2))
285 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
286 return Err(TildeError::new(
287 ErrorKind::ParseError,
288 "should start with ~^",
289 ));
290 }
291
292 Ok(Tilde {
293 len: 2,
294 value: TildeKind::LoopEnd,
295 })
296 }
297
298 fn parse_cond(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
300 let mut char_buf = [0u8; 3]; let mut total_len = 0;
302 let mut cond_kind;
303 c.read(&mut char_buf)
304 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
305
306 match char_buf {
307 [b'~', b'[', ..] => {
308 total_len += 2;
309 cond_kind = TildeCondKind::Nil(false);
310 c.seek(SeekFrom::Current(-1))
311 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
312 }
313 [b'~', b'#', b'['] => {
314 total_len += 3;
315 cond_kind = TildeCondKind::Sharp;
316 }
317 [b'~', b'@', b'['] => {
318 total_len += 3;
319 cond_kind = TildeCondKind::At;
320 }
321 [b'~', b':', b'['] => {
322 total_len += 3;
323 cond_kind = TildeCondKind::Colon;
324 }
325 _ => {
326 c.seek(SeekFrom::Current(-3))
327 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
328 return Err(TildeError::new(
329 ErrorKind::ParseError,
330 "should start with ~[, ~#[, ~@[",
331 ));
332 }
333 }
334
335 let mut buffer = vec![];
336 let mut one_byte = [0_u8; 1];
337
338 let mut cache = vec![];
339 let mut result: Vec<Tilde> = vec![];
340
341 loop {
342 c.read_exact(&mut one_byte)
343 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
344 if one_byte == [0] {
345 break;
346 }
347
348 if one_byte == [b'~'] {
349 if !buffer.is_empty() {
350 cache.push(Tilde {
351 len: buffer.len(),
352 value: TildeKind::Text(
353 String::from_utf8(buffer.clone()).map_err(|e| {
354 TildeError::new(ErrorKind::ParseError, e.to_string())
355 })?,
356 ),
357 });
358 buffer.clear();
359 }
360
361 one_byte[0] = 0;
362 c.read_exact(&mut one_byte)
363 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
364 match one_byte {
365 [b':'] => {
366 one_byte[0] = 0;
367 c.read_exact(&mut one_byte)
368 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
369 if one_byte == [b';'] {
370 let cache_len = cache.iter().map(|t: &Tilde| t.len()).sum::<usize>();
371 result.push(Tilde::new(cache_len, TildeKind::VecTilde(cache.clone())));
372 cond_kind.to_true();
373 cache.clear();
374 total_len += 3 + cache_len;
375 } else {
376 panic!()
377 }
378 }
379 [b';'] => {
380 let cache_len = cache.iter().map(|t: &Tilde| t.len()).sum::<usize>();
381 result.push(Tilde::new(cache_len, TildeKind::VecTilde(cache.clone())));
382 cache.clear();
383 total_len += 2 + cache_len;
384 }
385 [b']'] => {
386 let cache_len = cache.iter().map(|t: &Tilde| t.len()).sum::<usize>();
387 result.push(Tilde::new(cache_len, TildeKind::VecTilde(cache.clone())));
388 total_len += 2 + cache_len;
389 break;
390 }
391 _ => {
392 c.seek(SeekFrom::Current(-2))
393 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
394 let c = Self::parse(c)?;
395 cache.push(c);
396 }
397 }
398 one_byte[0] = 0;
399 } else {
400 buffer.push(one_byte[0]);
401 }
402 }
403
404 Ok(Tilde::new(total_len, TildeKind::Cond((result, cond_kind))))
405 }
406
407 #[cfg(test)]
408 fn parse_vec(
409 c: &mut Cursor<&'_ str>,
410 end_len: usize,
411 ) -> Result<Self, Box<dyn std::error::Error>> {
412 let mut bucket = vec![0; end_len].into_boxed_slice();
413 c.read_exact(&mut bucket)?;
414
415 let ss = String::from_utf8(bucket.as_ref().to_vec())?;
416 let mut inner_c = Cursor::new(ss.as_str());
418 let mut buf = vec![];
419 let mut result = vec![];
420 let mut total_len = 0;
421
422 loop {
423 inner_c.read_until(b'~', &mut buf)?;
425
426 match buf.as_slice() {
427 [b'~'] => {
428 inner_c.seek(SeekFrom::Current(-1))?;
429 }
430 [.., b'~'] => {
431 inner_c.seek(SeekFrom::Current(-1))?;
432 result.push(Tilde::new(
433 buf.len() - 1,
434 TildeKind::Text(String::from_utf8(buf[..buf.len() - 1].to_vec())?),
435 ));
436 total_len += buf.len() - 1;
437 }
438 [] => {
439 c.seek(SeekFrom::Current((end_len - total_len) as i64 * -1))?;
440 return Ok(Tilde::new(total_len, TildeKind::VecTilde(result)));
441 }
442 [..] => {
443 result.push(Tilde::new(
444 buf.len(),
445 TildeKind::Text(String::from_utf8(buf[..buf.len()].to_vec())?),
446 ));
447 total_len += buf.len();
448 c.seek(SeekFrom::Current((end_len - total_len) as i64 * -1))?;
449 return Ok(Tilde::new(total_len, TildeKind::VecTilde(result)));
450 }
451 }
452
453 let next = Tilde::parse(&mut inner_c)?;
454 total_len += next.len;
455 result.push(next);
456
457 buf.clear()
458 }
459 }
460
461 fn parse_value(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
463 let mut buf = vec![];
464 for t in [b'a', b'A'] {
466 c.read_until(t, &mut buf)
467 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
468 match buf.last() {
469 Some(b) if *b == t => return Ok(Tilde::new(buf.len(), TildeKind::Va)),
470 _ => (),
471 }
472 c.seek(SeekFrom::Current(-(buf.len() as i64)))
473 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
474 buf.clear();
475 }
476 Err(TildeError::new(
477 ErrorKind::ParseError,
478 "should start with ~a",
479 ))
480 }
481
482 fn parse_float(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
484 let mut buf = vec![];
485
486 for t in [b'$', b'f', b'F'] {
487 c.read_until(t, &mut buf)
488 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
489 match buf.last() {
490 Some(b) if *b == t => {
491 return Ok(Tilde::new(
492 buf.len(),
493 TildeKind::Float(Some(
494 String::from_utf8(
495 buf.get(1..buf.len() - 1).map_or(Vec::new(), |s| s.to_vec()),
496 )
497 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?,
498 )),
499 ))
500 }
501 _ => (),
502 }
503 c.seek(SeekFrom::Current(-(buf.len() as i64)))
504 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
505 buf.clear();
506 }
507 Err(TildeError::new(
508 ErrorKind::ParseError,
509 "cannot find the '$' or 'f'",
510 ))
511 }
512
513 fn parse_digit(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
515 let mut buf = vec![];
516
517 for t in [b'd', b'D'] {
518 c.read_until(t, &mut buf)
519 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
520 match buf.last() {
521 Some(b) if *b == t => {
522 let s = String::from_utf8(
523 buf.get(1..buf.len() - 1).map_or(Vec::new(), |s| s.to_vec()),
524 )
525 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
526 return Ok(Tilde::new(
527 buf.len(),
528 if &s == "" {
529 TildeKind::Digit(None)
530 } else {
531 TildeKind::Digit(Some(s))
532 },
533 ));
534 }
535 _ => (),
536 }
537 c.seek(SeekFrom::Current(-(buf.len() as i64)))
538 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
539 buf.clear();
540 }
541 Err(TildeError::new(
542 ErrorKind::ParseError,
543 "cannot find the 'd' or 'D'",
544 ))
545 }
546
547 fn parse_star(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
549 let mut char_buf = [0u8; 3]; c.read(&mut char_buf)
551 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
552
553 match char_buf {
554 [b'~', b':', b'*'] => Ok(Self {
555 len: 3,
556 value: TildeKind::Star(StarKind::Hop),
557 }),
558 [b'~', b'*', ..] => {
559 c.seek(SeekFrom::Current(-1))
560 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
561 Ok(Self {
562 len: 2,
563 value: TildeKind::Star(StarKind::Skip),
564 })
565 }
566 _ => {
567 c.seek(SeekFrom::Current(-3))
568 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
569 return Err(TildeError::new(
570 ErrorKind::ParseError,
571 "should start with ~* or ~:*",
572 ));
573 }
574 }
575 }
576
577 fn parse_tildes(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
578 let mut char_buf = [0u8; 3]; c.read(&mut char_buf)
580 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
581 match char_buf {
582 [b'~', n @ _, b'~'] => Ok(Self {
583 len: 3,
584 value: TildeKind::Tildes(
585 String::from_utf8(vec![n])
586 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?
587 .parse::<usize>()
588 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?,
589 ),
590 }),
591 _ => {
592 c.seek(SeekFrom::Current(-3))
593 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
594 return Err(TildeError::new(
595 ErrorKind::ParseError,
596 "should start with ~n~",
597 ));
598 }
599 }
600 }
601
602 fn parse_standard(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
603 let mut buf = vec![];
604 let mut one_byte = [0; 1];
605 loop {
606 if c.read(&mut one_byte)
607 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?
608 == 0
609 {
610 c.seek(SeekFrom::Current(-(buf.len() as i64)))
611 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
612 return Err(TildeError::new(
613 ErrorKind::ParseError,
614 "cannot find the 's' or 'S'",
615 ));
616 }
617
618 match one_byte[0] {
619 b's' | b'S' => return Ok(Tilde::new(buf.len() + 1, TildeKind::Standard)),
620 _ => buf.extend_from_slice(&one_byte),
621 }
622 }
623 }
624
625 fn parse_char(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
626 let mut char_buf = [0u8; 3]; c.read(&mut char_buf)
628 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
629
630 match char_buf {
631 [b'~', b'@', b'c' | b'C'] => Ok(Self {
632 len: 3,
633 value: TildeKind::Char(CharKind::At),
634 }),
635 [b'~', b'c' | b'C', ..] => {
636 c.seek(SeekFrom::Current(-1))
637 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
638 Ok(Self {
639 len: 2,
640 value: TildeKind::Char(CharKind::Nil),
641 })
642 }
643 _ => {
644 c.seek(SeekFrom::Current(-3))
645 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
646 return Err(TildeError::new(
647 ErrorKind::ParseError,
648 "should start with ~c or ~@c",
649 ));
650 }
651 }
652 }
653
654 fn parse_radix(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
655 let mut buf = [0u8; 1];
656 let mut bucket = vec![];
657 loop {
658 if c.read(&mut buf)
659 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?
660 == 0
661 || buf[0] == 0_u8
662 {
663 return Err(TildeError::new(ErrorKind::ParseError, "read to end"));
664 }
665
666 bucket.extend_from_slice(&buf);
667 if buf[0] == b'R' || buf[0] == b'r' {
668 break;
669 }
670
671 buf[0] = 0u8;
672 }
673
674 let whole = String::from_utf8(bucket[1..].to_vec())
675 .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?;
676
677 let mut splited_bucket = whole.split(',').collect::<VecDeque<_>>();
678
679 let parse_usize_helper = |a: &str| -> Result<Option<usize>, TildeError> {
683 if a.len() == 0 {
684 Ok(None)
685 } else {
686 Ok(Some(a.parse::<usize>().map_err(|e| {
687 TildeError::new(ErrorKind::ParseError, e.to_string())
688 })?))
689 }
690 };
691
692 let parse_u8_helper = |a: &str| -> Result<Option<u8>, TildeError> {
693 if a.len() == 0 {
694 Ok(None)
695 } else {
696 Ok(Some(a.parse::<u8>().map_err(|e| {
697 TildeError::new(ErrorKind::ParseError, e.to_string())
698 })?))
699 }
700 };
701
702 let parse_char_helper = |a: &str| -> Result<Option<char>, TildeError> {
704 if a.len() == 0 {
705 Ok(None)
706 } else {
707 Ok(a.chars().last())
708 }
709 };
710
711 let parse_radix_flag = |a: &str| -> Result<(Option<usize>, Option<RadixFlag>), TildeError> {
713 match &a.split(':').collect::<Vec<_>>()[..] {
714 ["", "R"] => Ok((None, Some(RadixFlag::Colon))),
715 ["@R"] => Ok((None, Some(RadixFlag::At))),
716 ["", "@R"] => Ok((None, Some(RadixFlag::AtColon))),
717 ["R"] => Ok((None, None)),
718 [n @ _, "R"] => Ok((parse_usize_helper(n)?, Some(RadixFlag::Colon))),
719 [n @ _] if n.ends_with("R") => Ok((parse_usize_helper(&n[0..n.len() - 1])?, None)),
720 _ => Err(TildeError::new(
721 ErrorKind::ParseError,
722 format!("Parsing the radix flag has problem: {}", a),
723 )),
724 }
725 };
726
727 let flag;
728 let radix;
729 let mut mincol = None;
730 let mut padchar = None;
731 let mut commachar = None;
732 let mut comma_interval = None;
733
734 if splited_bucket.len() == 1 {
737 let ra = splited_bucket.pop_front().unwrap();
738 let pair = parse_radix_flag(&ra)?;
739 (radix, flag) = (pair.0.map(|x| x as u8), pair.1)
740 } else if splited_bucket.len() == 5 {
741 radix = parse_u8_helper(splited_bucket.pop_front().unwrap())?;
742 mincol = parse_usize_helper(splited_bucket.pop_front().unwrap())?;
743 padchar = parse_char_helper(splited_bucket.pop_front().unwrap())?;
744 commachar = parse_char_helper(splited_bucket.pop_front().unwrap())?;
745
746 let ra = splited_bucket.pop_front().unwrap();
747 (comma_interval, flag) = parse_radix_flag(&ra)?;
748 } else {
749 return Err(TildeError::new(
750 ErrorKind::ParseError,
751 "The number of radix interval spaces should be 1 or 5",
752 ));
753 }
754
755 Ok(Self::new(
756 bucket.len(),
757 TildeKind::Radix((radix, mincol, padchar, commachar, comma_interval, flag)),
758 ))
759 }
760
761 }
763
764#[cfg(test)]
765mod tests {
766 use super::*;
767
768 #[test]
769 fn test_cursor() {
770 let mut testcase0 = Cursor::new("abcd");
771 assert_eq!(testcase0.position(), 0);
772
773 let mut buffer: [u8; 1] = [0; 1];
774 testcase0.set_position(2);
775 let _ = testcase0.read(&mut buffer);
776 assert_eq!(buffer[0], b'c');
777 }
778
779 #[test]
780 fn test_parse_va() -> Result<(), Box<dyn std::error::Error>> {
781 let mut case = Cursor::new("~a");
782 assert_eq!(Tilde::parse_value(&mut case)?, Tilde::new(2, TildeKind::Va));
783
784 let mut case = Cursor::new("~A");
785 assert_eq!(Tilde::parse_value(&mut case)?, Tilde::new(2, TildeKind::Va));
786 Ok(())
787 }
788
789 #[test]
790 fn test_parse_loop() -> Result<(), Box<dyn std::error::Error>> {
791 let mut case = Cursor::new("~{~}");
792
793 assert_eq!(
794 Tilde::parse_loop(&mut case)?,
795 Tilde::new(4, TildeKind::Loop((Vec::new(), TildeLoopKind::Nil)))
796 );
797
798 let mut case = Cursor::new("~{a bc~}");
799
800 assert_eq!(
801 Tilde::parse_loop(&mut case)?,
802 Tilde::new(
803 8,
804 TildeKind::Loop((
805 vec![Tilde {
806 len: 4,
807 value: TildeKind::Text(String::from("a bc"))
808 }],
809 TildeLoopKind::Nil
810 ))
811 ),
812 );
813
814 let mut case = Cursor::new("~{a bc~a~}");
815
816 assert_eq!(
817 Tilde::parse_loop(&mut case)?,
818 Tilde::new(
819 10,
820 TildeKind::Loop((
821 vec![
822 Tilde {
823 len: 4,
824 value: TildeKind::Text(String::from("a bc"))
825 },
826 Tilde {
827 len: 2,
828 value: TildeKind::Va,
829 }
830 ],
831 TildeLoopKind::Nil
832 ))
833 )
834 );
835
836 let mut case = Cursor::new("~{~aa bc~a~}");
837
838 assert_eq!(
839 Tilde::parse_loop(&mut case)?,
840 Tilde::new(
841 12,
842 TildeKind::Loop((
843 vec![
844 Tilde {
845 len: 2,
846 value: TildeKind::Va,
847 },
848 Tilde {
849 len: 4,
850 value: TildeKind::Text(String::from("a bc"))
851 },
852 Tilde {
853 len: 2,
854 value: TildeKind::Va,
855 }
856 ],
857 TildeLoopKind::Nil
858 ))
859 )
860 );
861
862 let mut case = Cursor::new("~@{~a~}");
863
864 assert_eq!(
865 Tilde::parse_loop(&mut case)?,
866 Tilde::new(
867 7,
868 TildeKind::Loop((
869 vec![Tilde {
870 len: 2,
871 value: TildeKind::Va,
872 },],
873 TildeLoopKind::At
874 ))
875 )
876 );
877
878 let mut case = Cursor::new("~@{~a~^, ~}");
879
880 assert_eq!(
881 Tilde::parse_loop(&mut case)?,
882 Tilde::new(
883 11,
884 TildeKind::Loop((
885 vec![
886 Tilde {
887 len: 2,
888 value: TildeKind::Va,
889 },
890 Tilde {
891 len: 2,
892 value: TildeKind::LoopEnd,
893 },
894 Tilde {
895 len: 2,
896 value: TildeKind::Text(", ".to_string()),
897 }
898 ],
899 TildeLoopKind::At
900 ))
901 )
902 );
903
904 let mut case = Cursor::new("~{~a~:}");
905 assert_eq!(
906 Tilde::parse_loop(&mut case)?,
907 Tilde::new(
908 7,
909 TildeKind::Loop((
910 vec![Tilde {
911 len: 2,
912 value: TildeKind::Va,
913 },],
914 TildeLoopKind::NilColon
915 ))
916 )
917 );
918
919 Ok(())
920 }
921
922 #[test]
923 fn test_parse_float() -> Result<(), Box<dyn std::error::Error>> {
924 let mut case = Cursor::new("~$");
925 assert_eq!(
926 Tilde::parse_float(&mut case)?,
927 Tilde::new(2, TildeKind::Float(Some(String::new())))
928 );
929
930 let mut case = Cursor::new("~5$");
931 assert_eq!(
932 Tilde::parse_float(&mut case)?,
933 Tilde::new(3, TildeKind::Float(Some("5".to_string())))
934 );
935
936 let mut case = Cursor::new("~,5f");
937 assert_eq!(
938 Tilde::parse_float(&mut case)?,
939 Tilde::new(4, TildeKind::Float(Some(",5".to_string())))
940 );
941
942 Ok(())
943 }
944
945 #[test]
946 fn test_scan_for_kind() -> Result<(), Box<dyn std::error::Error>> {
947 let case = "~a";
948 let mut c = Cursor::new(case);
949 let f = Tilde::scan_for_kind(&mut c)?;
950
951 assert_eq!(Tilde::new(2, TildeKind::Va), f(&mut c)?);
958 Ok(())
959 }
960
961 #[test]
962 fn test_parse_vec() -> Result<(), Box<dyn std::error::Error>> {
963 let mut case = Cursor::new("~a and ~a~a~a");
964 assert_eq!(
965 Tilde::parse_vec(&mut case, 9)?,
966 Tilde::new(
967 9,
968 TildeKind::VecTilde(vec![
969 Tilde {
970 len: 2,
971 value: TildeKind::Va
972 },
973 Tilde {
974 len: 5,
975 value: TildeKind::Text(String::from(" and "))
976 },
977 Tilde {
978 len: 2,
979 value: TildeKind::Va
980 }
981 ])
982 )
983 );
984
985 let mut rest = vec![];
987 case.read_to_end(&mut rest)?;
988 assert_eq!(String::from_utf8(rest)?, "~a~a");
989
990 let mut case = Cursor::new("~a a");
992 assert!(Tilde::parse_vec(&mut case, 9).is_err());
993
994 let mut case = Cursor::new("a");
996 assert_eq!(
997 Tilde::parse_vec(&mut case, 1)?,
998 Tilde::new(
999 1,
1000 TildeKind::VecTilde(vec![Tilde {
1001 len: 1,
1002 value: TildeKind::Text(String::from("a"))
1003 }])
1004 )
1005 );
1006
1007 Ok(())
1008 }
1009
1010 #[test]
1011 fn test_parse_cond() -> Result<(), Box<dyn std::error::Error>> {
1012 let mut case = Cursor::new("~[~]");
1013
1014 assert_eq!(
1015 Tilde::parse_cond(&mut case)?,
1016 Tilde::new(
1017 4,
1018 TildeKind::Cond((
1019 vec![Tilde {
1020 len: 0,
1021 value: TildeKind::VecTilde(vec![])
1022 }],
1023 TildeCondKind::Nil(false)
1024 ))
1025 )
1026 );
1027
1028 let mut case = Cursor::new("~[cero~]");
1029
1030 assert_eq!(
1031 Tilde::parse_cond(&mut case)?,
1032 Tilde::new(
1033 8,
1034 TildeKind::Cond((
1035 vec![Tilde {
1036 len: 4,
1037 value: TildeKind::VecTilde(vec![Tilde::new(
1038 4,
1039 TildeKind::Text(String::from("cero"))
1040 )]),
1041 }],
1042 TildeCondKind::Nil(false)
1043 ))
1044 ),
1045 );
1046
1047 let mut case = Cursor::new("~[cero~;uno~;dos~]");
1048
1049 assert_eq!(
1050 Tilde::parse_cond(&mut case)?,
1051 Tilde::new(
1052 18,
1053 TildeKind::Cond((
1054 vec![
1055 Tilde {
1056 len: 4,
1057 value: TildeKind::VecTilde(vec![Tilde::new(
1058 4,
1059 TildeKind::Text(String::from("cero"))
1060 )])
1061 },
1062 Tilde {
1063 len: 3,
1064 value: TildeKind::VecTilde(vec![Tilde::new(
1065 3,
1066 TildeKind::Text(String::from("uno"))
1067 )])
1068 },
1069 Tilde {
1070 len: 3,
1071 value: TildeKind::VecTilde(vec![Tilde::new(
1072 3,
1073 TildeKind::Text(String::from("dos"))
1074 )])
1075 },
1076 ],
1077 TildeCondKind::Nil(false)
1078 ))
1079 )
1080 );
1081
1082 let mut case = Cursor::new("~[cero~;uno~;~]");
1083
1084 assert_eq!(
1085 Tilde::parse_cond(&mut case)?,
1086 Tilde::new(
1087 15,
1088 TildeKind::Cond((
1089 vec![
1090 Tilde {
1091 len: 4,
1092 value: TildeKind::VecTilde(vec![Tilde::new(
1093 4,
1094 TildeKind::Text(String::from("cero"))
1095 )])
1096 },
1097 Tilde {
1098 len: 3,
1099 value: TildeKind::VecTilde(vec![Tilde::new(
1100 3,
1101 TildeKind::Text(String::from("uno"))
1102 )])
1103 },
1104 Tilde {
1105 len: 0,
1106 value: TildeKind::VecTilde(vec![])
1107 },
1108 ],
1109 TildeCondKind::Nil(false)
1110 ))
1111 )
1112 );
1113
1114 let mut case = Cursor::new("~:[cero~;uno~]");
1115 assert_eq!(
1116 Tilde::parse_cond(&mut case)?,
1117 Tilde::new(
1118 14,
1119 TildeKind::Cond((
1120 vec![
1121 Tilde {
1122 len: 4,
1123 value: TildeKind::VecTilde(vec![Tilde::new(
1124 4,
1125 TildeKind::Text(String::from("cero"))
1126 )])
1127 },
1128 Tilde {
1129 len: 3,
1130 value: TildeKind::VecTilde(vec![Tilde::new(
1131 3,
1132 TildeKind::Text(String::from("uno"))
1133 )])
1134 },
1135 ],
1136 TildeCondKind::Colon
1137 ))
1138 )
1139 );
1140
1141 let mut case = Cursor::new("~[cero~;uno~:;dos~]");
1142
1143 assert_eq!(
1144 Tilde::parse_cond(&mut case)?,
1145 Tilde::new(
1146 19,
1147 TildeKind::Cond((
1148 vec![
1149 Tilde {
1150 len: 4,
1151 value: TildeKind::VecTilde(vec![Tilde::new(
1152 4,
1153 TildeKind::Text(String::from("cero"))
1154 )])
1155 },
1156 Tilde {
1157 len: 3,
1158 value: TildeKind::VecTilde(vec![Tilde::new(
1159 3,
1160 TildeKind::Text(String::from("uno"))
1161 )])
1162 },
1163 Tilde {
1164 len: 3,
1165 value: TildeKind::VecTilde(vec![Tilde::new(
1166 3,
1167 TildeKind::Text(String::from("dos"))
1168 )])
1169 },
1170 ],
1171 TildeCondKind::Nil(true)
1172 ))
1173 )
1174 );
1175
1176 let mut case = Cursor::new("~#[NONE~;~a~;~a and ~a~:;~a, ~a~]");
1177
1178 assert_eq!(
1179 Tilde::parse_cond(&mut case)?,
1180 Tilde::new(
1181 33,
1182 TildeKind::Cond((
1183 vec![
1184 Tilde {
1185 len: 4,
1186 value: TildeKind::VecTilde(vec![Tilde::new(
1187 4,
1188 TildeKind::Text(String::from("NONE"))
1189 )])
1190 },
1191 Tilde {
1192 len: 2,
1193 value: TildeKind::VecTilde(vec![Tilde::new(2, TildeKind::Va)])
1194 },
1195 Tilde {
1196 len: 9,
1197 value: TildeKind::VecTilde(vec![
1198 Tilde {
1199 len: 2,
1200 value: TildeKind::Va
1201 },
1202 Tilde {
1203 len: 5,
1204 value: TildeKind::Text(String::from(" and "))
1205 },
1206 Tilde {
1207 len: 2,
1208 value: TildeKind::Va,
1209 }
1210 ]),
1211 },
1212 Tilde {
1213 len: 6,
1214 value: TildeKind::VecTilde(vec![
1215 Tilde {
1216 len: 2,
1217 value: TildeKind::Va
1218 },
1219 Tilde {
1220 len: 2,
1221 value: TildeKind::Text(String::from(", "))
1222 },
1223 Tilde {
1224 len: 2,
1225 value: TildeKind::Va,
1226 }
1227 ]),
1228 },
1229 ],
1230 TildeCondKind::Sharp
1231 ))
1232 )
1233 );
1234
1235 let mut case = Cursor::new("~@[x = ~a ~]~@[y = ~a~]");
1236 assert_eq!(
1237 Tilde::parse_cond(&mut case)?,
1238 Tilde::new(
1239 12,
1240 TildeKind::Cond((
1241 vec![Tilde {
1242 len: 7,
1243 value: TildeKind::VecTilde(vec![
1244 Tilde {
1245 len: 4,
1246 value: TildeKind::Text("x = ".into())
1247 },
1248 Tilde {
1249 len: 2,
1250 value: TildeKind::Va
1251 },
1252 Tilde {
1253 len: 1,
1254 value: TildeKind::Text(" ".into())
1255 }
1256 ])
1257 }],
1258 TildeCondKind::At
1259 ))
1260 )
1261 );
1262
1263 assert_eq!(
1265 Tilde::parse_cond(&mut case)?,
1266 Tilde::new(
1267 11,
1268 TildeKind::Cond((
1269 vec![Tilde {
1270 len: 6,
1271 value: TildeKind::VecTilde(vec![
1272 Tilde {
1273 len: 4,
1274 value: TildeKind::Text("y = ".into())
1275 },
1276 Tilde {
1277 len: 2,
1278 value: TildeKind::Va
1279 },
1280 ])
1281 }],
1282 TildeCondKind::At
1283 ))
1284 )
1285 );
1286
1287 Ok(())
1288 }
1289
1290 #[test]
1291 fn test_parse_star() -> Result<(), Box<dyn std::error::Error>> {
1292 let mut case = Cursor::new("~:*");
1293 assert_eq!(
1294 Tilde::parse(&mut case)?,
1295 Tilde::new(3, TildeKind::Star(StarKind::Hop))
1296 );
1297
1298 let mut case = Cursor::new("~*");
1299 assert_eq!(
1300 Tilde::parse(&mut case)?,
1301 Tilde::new(2, TildeKind::Star(StarKind::Skip))
1302 );
1303 Ok(())
1304 }
1305
1306 #[test]
1307 fn test_parse_tildes() -> Result<(), Box<dyn std::error::Error>> {
1308 let mut case = Cursor::new("~9~");
1309 assert_eq!(
1310 Tilde::parse(&mut case)?,
1311 Tilde::new(3, TildeKind::Tildes(9))
1312 );
1313
1314 let mut case = Cursor::new("~0~");
1315 assert_eq!(
1316 Tilde::parse(&mut case)?,
1317 Tilde::new(3, TildeKind::Tildes(0))
1318 );
1319 Ok(())
1320 }
1321
1322 #[test]
1323 fn test_parse_standard() -> Result<(), Box<dyn std::error::Error>> {
1324 let mut case = Cursor::new("~s");
1325 assert_eq!(Tilde::parse(&mut case)?, Tilde::new(2, TildeKind::Standard));
1326
1327 let mut case = Cursor::new("~S");
1328 assert_eq!(Tilde::parse(&mut case)?, Tilde::new(2, TildeKind::Standard));
1329
1330 let mut case = Cursor::new("~S superbowl");
1331 assert_eq!(Tilde::parse(&mut case)?, Tilde::new(2, TildeKind::Standard));
1332
1333 Ok(())
1334 }
1335
1336 #[test]
1337 fn test_parse_char() -> Result<(), Box<dyn std::error::Error>> {
1338 let mut case = Cursor::new("~c");
1339 assert_eq!(
1340 Tilde::parse(&mut case)?,
1341 Tilde::new(2, TildeKind::Char(CharKind::Nil))
1342 );
1343
1344 let mut case = Cursor::new("~@c");
1345 assert_eq!(
1346 Tilde::parse(&mut case)?,
1347 Tilde::new(3, TildeKind::Char(CharKind::At))
1348 );
1349
1350 Ok(())
1351 }
1352
1353 #[test]
1354 fn test_parse_radix() -> Result<(), Box<dyn std::error::Error>> {
1355 let mut case = Cursor::new("~2,8,0, ,R");
1357 assert_eq!(
1358 Tilde::parse(&mut case)?,
1359 Tilde::new(
1360 10,
1361 TildeKind::Radix((Some(2), Some(8), Some('0'), Some(' '), None, None))
1362 )
1363 );
1364
1365 let mut case = Cursor::new("~,,,,R");
1366 assert_eq!(
1367 Tilde::parse(&mut case)?,
1368 Tilde::new(6, TildeKind::Radix((None, None, None, None, None, None)))
1369 );
1370
1371 let mut case = Cursor::new("~2,8,0, ,4:R");
1372 assert_eq!(
1373 Tilde::parse(&mut case)?,
1374 Tilde::new(
1375 12,
1376 TildeKind::Radix((
1377 Some(2),
1378 Some(8),
1379 Some('0'),
1380 Some(' '),
1381 Some(4),
1382 Some(RadixFlag::Colon)
1383 ))
1384 )
1385 );
1386
1387 let mut case = Cursor::new("~2,8,0, ,10:R");
1388 assert_eq!(
1389 Tilde::parse(&mut case)?,
1390 Tilde::new(
1391 13,
1392 TildeKind::Radix((
1393 Some(2),
1394 Some(8),
1395 Some('0'),
1396 Some(' '),
1397 Some(10),
1398 Some(RadixFlag::Colon)
1399 ))
1400 )
1401 );
1402
1403 let mut case = Cursor::new("~3,,, ,2:R");
1404 assert_eq!(
1405 Tilde::parse(&mut case)?,
1406 Tilde::new(
1407 10,
1408 TildeKind::Radix((
1409 Some(3),
1410 None,
1411 None,
1412 Some(' '),
1413 Some(2),
1414 Some(RadixFlag::Colon)
1415 ))
1416 )
1417 );
1418
1419 let mut case = Cursor::new("~2:R");
1420 assert_eq!(
1421 Tilde::parse(&mut case)?,
1422 Tilde::new(
1423 4,
1424 TildeKind::Radix((Some(2), None, None, None, None, Some(RadixFlag::Colon)))
1425 )
1426 );
1427
1428 let mut case = Cursor::new("~2R");
1429 assert_eq!(
1430 Tilde::parse(&mut case)?,
1431 Tilde::new(3, TildeKind::Radix((Some(2), None, None, None, None, None)))
1432 );
1433
1434 let mut case = Cursor::new("~R");
1435 assert_eq!(
1436 Tilde::parse(&mut case)?,
1437 Tilde::new(2, TildeKind::Radix((None, None, None, None, None, None)))
1438 );
1439
1440 let mut case = Cursor::new("~:R");
1441 assert_eq!(
1442 Tilde::parse(&mut case)?,
1443 Tilde::new(
1444 3,
1445 TildeKind::Radix((None, None, None, None, None, Some(RadixFlag::Colon)))
1446 )
1447 );
1448
1449 let mut case = Cursor::new("~@R");
1450 assert_eq!(
1451 Tilde::parse(&mut case)?,
1452 Tilde::new(
1453 3,
1454 TildeKind::Radix((None, None, None, None, None, Some(RadixFlag::At)))
1455 )
1456 );
1457
1458 let mut case = Cursor::new("~:@R");
1459 assert_eq!(
1460 Tilde::parse(&mut case)?,
1461 Tilde::new(
1462 4,
1463 TildeKind::Radix((None, None, None, None, None, Some(RadixFlag::AtColon)))
1464 )
1465 );
1466
1467 let mut case = Cursor::new(r#"~2,,,\a,4:R"#);
1468 assert_eq!(
1469 Tilde::parse(&mut case)?,
1470 Tilde::new(
1471 11,
1472 TildeKind::Radix((
1473 Some(2),
1474 None,
1475 None,
1476 Some('a'),
1477 Some(4),
1478 Some(RadixFlag::Colon)
1479 ))
1480 )
1481 );
1482
1483 Ok(())
1484 }
1485}