cl_format/tildes/
tilde_kinds.rs

1use super::Tilde;
2
3use cl_format_macros::TildeAble;
4use std::fmt::Debug;
5
6#[doc = "Error type for tildes parsing"]
7#[derive(Debug)]
8pub struct TildeError {
9    kind: ErrorKind,
10    msg: String,
11}
12
13impl TildeError {
14    pub fn new(kind: ErrorKind, msg: impl AsRef<str>) -> Self {
15        Self {
16            kind,
17            msg: msg.as_ref().to_string(),
18        }
19    }
20}
21
22impl std::error::Error for TildeError {}
23
24impl std::fmt::Display for TildeError {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(f, "TilderError {:?}: {}", self.kind, self.msg)
27    }
28}
29
30#[doc = "ErrorKind"]
31#[derive(Debug)]
32pub enum ErrorKind {
33    ParseError,
34    RevealError,
35    EmptyImplenmentError,
36    FormatError,
37}
38
39#[doc = "TildeCondKind"]
40#[derive(Debug, PartialEq, Clone)]
41pub enum TildeCondKind {
42    Nil(bool), // ~[, bool for the last ~:;
43    Sharp,     // ~#[
44    At,        // ~@[
45    Colon,     // ~:[
46}
47
48#[doc = "TildeLoopKind"]
49#[derive(Debug, PartialEq, Clone)]
50pub enum TildeLoopKind {
51    Nil,      // ~{~}
52    NilColon, // ~{~:}
53    At,       // ~@{~}
54}
55
56impl TildeCondKind {
57    pub fn to_true(&mut self) {
58        match self {
59            TildeCondKind::Nil(_) => *self = TildeCondKind::Nil(true),
60            _ => (),
61        }
62    }
63}
64
65#[doc = "StarKind"]
66#[derive(Debug, PartialEq, Clone)]
67pub enum StarKind {
68    Hop,
69    Skip,
70}
71
72#[derive(Debug)]
73pub(super) struct TildeNil;
74
75#[doc = "CharKind"]
76#[derive(Debug, PartialEq, Clone)]
77pub enum CharKind {
78    Nil,
79    At,
80}
81
82#[doc = "Radix flag ~@R, ~:R, and ~:@R"]
83#[derive(Debug, PartialEq, Clone)]
84pub enum RadixFlag {
85    At,      // ~@R
86    Colon,   // ~:R
87    AtColon, // ~:@R
88}
89
90#[doc = "TildeKind is the enum that including all potential kind.
91
92The most of variants inside has its implement trait. Like the `~d` is `TildeKind::Digit` and the type that can be revealed as `~a` should implement `TildeKindDigit` trait.
93
94Check README for custom types.
95"]
96#[derive(Debug, PartialEq, TildeAble, Clone)]
97pub enum TildeKind {
98    #[implTo(char)]
99    /// `~C` and `~:C`
100    Char(CharKind),
101
102    /// `~$`, `~5$`, and `~f`
103    Float(Option<String>),
104
105    #[implTo(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize)]
106    /// Tilde R: Radix, [doc](http://www.lispworks.com/documentation/lw50/CLHS/Body/22_cba.htm)
107    Radix(
108        (
109            Option<u8>,        // radix
110            Option<usize>,     // mincol
111            Option<char>,      // padchar
112            Option<char>,      // commachar
113            Option<usize>,     // comma-interval
114            Option<RadixFlag>, // flag
115        ),
116    ),
117
118    #[implTo(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize)]
119    /// `~d`, `~:d`, and `~:@d`
120    Digit(Option<String>),
121
122    #[implTo(
123        f32, f64, char, i8, i16, i32, i64, i128, isize, bool, u8, u16, u32, u64, u128, usize,
124        String, TildeNil
125    )]
126    /// `~a`
127    Va,
128
129    /// `~*` and `~:*`
130    Star(StarKind),
131
132    #[implTo(f32, f64, char, i32, i64, usize, bool, u32, u64, String)]
133    /// `~s`
134    Standard,
135
136    /// for loop expression
137    Loop((Vec<Tilde>, TildeLoopKind)),
138
139    /// for loop stop, `~^`
140    LoopEnd,
141
142    /// tilde itself
143    Tildes(usize),
144
145    #[implTo(usize, bool)]
146    /// `~[` and `~]` condition
147    Cond((Vec<Tilde>, TildeCondKind)),
148
149    /// text inside the tilde
150    Text(String),
151
152    #[implTo(TildeNil)]
153    /// Vec of tildes
154    VecTilde(Vec<Tilde>),
155}
156
157impl TildeKind {
158    pub fn match_reveal(&self, arg: &dyn TildeAble, buf: &mut String) -> Result<(), TildeError> {
159        //dbg!(arg);
160        //dbg!(self);
161        match self {
162            TildeKind::Char(_) => {
163                let a = arg.into_tildekind_char().ok_or::<TildeError>(
164                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Va").into(),
165                )?;
166
167                return a.format(self, buf);
168            }
169            TildeKind::Float(_) => {
170                let a = arg.into_tildekind_float().ok_or::<TildeError>(
171                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Va").into(),
172                )?;
173
174                return a.format(self, buf);
175            }
176            TildeKind::Digit(_) => {
177                let a = arg.into_tildekind_digit().ok_or::<TildeError>(
178                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Va").into(),
179                )?;
180
181                return a.format(self, buf);
182            }
183            TildeKind::Va => {
184                //dbg!(&arg);
185                let a = arg.into_tildekind_va().ok_or::<TildeError>(
186                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Va").into(),
187                )?;
188
189                return a.format(self, buf);
190            }
191            TildeKind::Loop(_) => {
192                let a = arg.into_tildekind_loop().ok_or::<TildeError>(
193                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Loop").into(),
194                )?;
195
196                return a.format(self, buf);
197            }
198            TildeKind::LoopEnd => {
199                Err(TildeError::new(ErrorKind::RevealError, "loop end cannot reveal").into())
200            }
201            TildeKind::Tildes(n) => {
202                buf.push_str(
203                    String::from_utf8(vec![b'~'; *n])
204                        .map_err(|e| TildeError::new(ErrorKind::RevealError, e.to_string()))?
205                        .as_str(),
206                );
207                Ok(())
208            }
209            TildeKind::Text(s) => {
210                buf.push_str(s);
211                Ok(())
212            }
213            TildeKind::VecTilde(_) => {
214                let a = arg.into_tildekind_vectilde().ok_or::<TildeError>(
215                    TildeError::new(ErrorKind::RevealError, "cannot reveal to VecTilde").into(),
216                )?;
217
218                return a.format(self, buf);
219            }
220            TildeKind::Cond((_, _)) => {
221                let a = arg.into_tildekind_cond().ok_or::<TildeError>(
222                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Cond").into(),
223                )?;
224                return a.format(self, buf);
225            }
226            TildeKind::Star(_) => {
227                let a = arg.into_tildekind_star().ok_or::<TildeError>(
228                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Star").into(),
229                )?;
230                return a.format(self, buf);
231            }
232            TildeKind::Standard => {
233                let a = arg.into_tildekind_standard().ok_or::<TildeError>(
234                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Standard").into(),
235                )?;
236                return a.format(self, buf);
237            }
238            TildeKind::Radix(_) => {
239                let a = arg.into_tildekind_radix().ok_or::<TildeError>(
240                    TildeError::new(ErrorKind::RevealError, "cannot reveal to Radix").into(),
241                )?;
242                return a.format(self, buf);
243            } //_ => unimplemented!(),
244        }
245    }
246}