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), Sharp, At, Colon, }
47
48#[doc = "TildeLoopKind"]
49#[derive(Debug, PartialEq, Clone)]
50pub enum TildeLoopKind {
51 Nil, NilColon, At, }
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, Colon, AtColon, }
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 Char(CharKind),
101
102 Float(Option<String>),
104
105 #[implTo(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize)]
106 Radix(
108 (
109 Option<u8>, Option<usize>, Option<char>, Option<char>, Option<usize>, Option<RadixFlag>, ),
116 ),
117
118 #[implTo(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize)]
119 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 Va,
128
129 Star(StarKind),
131
132 #[implTo(f32, f64, char, i32, i64, usize, bool, u32, u64, String)]
133 Standard,
135
136 Loop((Vec<Tilde>, TildeLoopKind)),
138
139 LoopEnd,
141
142 Tildes(usize),
144
145 #[implTo(usize, bool)]
146 Cond((Vec<Tilde>, TildeCondKind)),
148
149 Text(String),
151
152 #[implTo(TildeNil)]
153 VecTilde(Vec<Tilde>),
155}
156
157impl TildeKind {
158 pub fn match_reveal(&self, arg: &dyn TildeAble, buf: &mut String) -> Result<(), TildeError> {
159 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 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 } }
245 }
246}