cl_format/
tildes.rs

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    /*
42    ===============================
43    parse functions below
44    ===============================
45    */
46
47    /// start from '~' to the key char of tilde kind
48    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            //dbg!(&bucket);
77            if !escape {
78                match &bucket[..] {
79                    [.., b'\\'] => {
80                        // escape the next one
81                        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()))?; // back to start
87                        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()))?; // back to start
92                        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()))?; // back to start
97                        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()))?; // back to start
102                        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()))?; // back to start
107                        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()))?; // back to start
112                        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()))?; // back to start
117                        return Ok(Box::new(Self::parse_star));
118                    }
119                    [.., _, b'~'] => {
120                        //:= can only parse the one digit number
121                        c.seek(SeekFrom::Current(-buf_offset))
122                            .map_err(|e| TildeError::new(ErrorKind::ParseError, e.to_string()))?; // back to start
123                        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()))?; // back to start
128                        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()))?; // back to start
133                        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()))?; // back to start
138                        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    /// cursor should located on '~'
155    pub fn parse(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
156        //dbg!(&c);
157        let parser = Self::scan_for_kind(c)?;
158        parser(c)
159    }
160
161    /// parse function for '~{~}'
162    fn parse_loop(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
163        let mut char_buf = [0u8; 3]; // three bytes
164        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            // read text until the next '~'
196            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            // read the tilde
270            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    /// parse the ~^ in loop
279    fn parse_loop_end(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
280        let mut char_buf = [0u8; 2]; // three bytes
281        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    /// parse the '~[~]'
299    fn parse_cond(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
300        let mut char_buf = [0u8; 3]; // three bytes
301        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        //dbg!(&ss);
417        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            // read text until the next '~'
424            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    /// parse function for '~a'
462    fn parse_value(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
463        let mut buf = vec![];
464        //:= this for in maybe re-write in helper function
465        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    /// parse the float
483    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    /// parse the digit
514    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    /// parse the star
548    fn parse_star(c: &mut Cursor<&'_ str>) -> Result<Self, TildeError> {
549        let mut char_buf = [0u8; 3]; // three bytes
550        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]; // three bytes
579        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]; // three bytes
627        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        //dbg!(&splited_bucket);
680
681        // helper function for parsing the usize
682        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        // helper function for parsing the char
703        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        // helper function for parsing the radix flag
712        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        // has to be 1 or 5
735        // if there is no comma
736        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    // more parsers functions below
762}
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        // let mut ss = String::new();
952        // c.read_to_string(&mut ss);
953        // dbg!(ss);
954        // c.seek(SeekFrom::Start(0));
955        //dbg!(f(&mut c));
956
957        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        //dbg!(&case.position());
986        let mut rest = vec![];
987        case.read_to_end(&mut rest)?;
988        assert_eq!(String::from_utf8(rest)?, "~a~a");
989
990        //
991        let mut case = Cursor::new("~a a");
992        assert!(Tilde::parse_vec(&mut case, 9).is_err());
993
994        //
995        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        // parse the second part
1264        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");
1356        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}