1use eyre::bail;
2use eyre::Result;
3use std::fmt;
4use toml::{Table, Value};
5use winnow::ascii::alphanumeric1;
6use winnow::ascii::dec_int;
7use winnow::ascii::space0;
8use winnow::combinator::alt;
9use winnow::combinator::delimited;
10use winnow::combinator::opt;
11use winnow::combinator::separated;
12use winnow::combinator::separated_pair;
13use winnow::combinator::seq;
14use winnow::error::StrContext;
15use winnow::error::StrContextValue;
16use winnow::prelude::*;
17use winnow::token::take_while;
18
19#[derive(Debug, Eq, PartialEq, Clone)]
24pub struct Range {
25 start: isize,
26 end: isize,
27}
28
29impl Range {
30 pub fn new(start: isize, end: isize) -> Self {
32 Self { start, end }
33 }
34
35 pub fn gen_range_indexes(&self, length: usize) -> Result<Vec<usize>> {
38 let length = length as isize;
39 let mut indexes: Vec<usize> = Vec::new();
40 match (self.start, self.end) {
42 (start, end) if start >= 0 && end < 0 => {
43 let end_fixed = (length + end) as usize;
45 let start = start as usize;
46 if end_fixed < start {
47 bail!("end < start ({:?})", self);
48 }
49
50 for n in start..=end_fixed {
51 indexes.push(n);
52 }
53 }
54 (start, end) if start < 0 && end >= 0 => {
55 let start_fixed = (length + start) as usize;
57 let end = end as usize;
58 if end < start_fixed {
59 bail!("end < start ({:?})", self);
60 }
61
62 for n in start_fixed..end {
63 indexes.push(n);
64 }
65 }
66 (start, end) if start >= 0 && end >= 0 => {
67 let start = start as usize;
69 let end = end as usize;
70 if end < start {
71 bail!("end < start ({:?})", self);
72 }
73
74 for n in start..end {
75 indexes.push(n);
76 }
77 }
78 (start, end) if start < 0 && end < 0 => {
79 let start_fixed = (length + start) as usize;
81 let end_fixed = (length + end) as usize;
82 if end_fixed < start_fixed {
83 bail!("end < start ({:?})", self);
84 }
85
86 for n in start_fixed..end_fixed {
87 indexes.push(n);
88 }
89 }
90 _ => {
91 unreachable!("If this happens I have an error in my range logic");
92 }
93 }
94 Ok(indexes)
95 }
96}
97
98fn number(s: &mut &str) -> PResult<isize> {
99 dec_int.parse_next(s)
100}
101
102#[derive(Debug, Eq, PartialEq, Clone)]
103pub enum Index {
104 Number(isize),
105 Range(Range),
106}
107
108fn range(s: &mut &str) -> PResult<Range> {
109 separated_pair(number, space_colon_space, number)
110 .map(|(start, end)| Range { start, end })
111 .parse_next(s)
112}
113
114fn index_range(s: &mut &str) -> PResult<Index> {
115 range.map(|r| Index::Range(r)).parse_next(s)
116}
117
118fn index_number(s: &mut &str) -> PResult<Index> {
119 number.map(|x| Index::Number(x)).parse_next(s)
120}
121
122fn index(s: &mut &str) -> PResult<Index> {
123 alt((index_range, index_number)).parse_next(s)
125}
126
127#[derive(Debug, Eq, PartialEq, Clone)]
128pub enum Op {
129 Dot,
131
132 Name(String),
134
135 BracketIndex(Vec<Index>),
139
140 BracketName(Vec<String>),
144}
145
146impl fmt::Display for Op {
147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
148 let repr = match self {
149 Op::Dot => String::from("."),
150 Op::Name(string) => {
151 format!("Op::Name({:?})", string)
152 }
153 Op::BracketIndex(indexes) => {
154 format!("Op::BracketIndex({:?})", indexes)
155 }
156 Op::BracketName(names) => {
157 format!("Op::BracketName({:?})", names)
158 }
159 };
160
161 write!(f, "{}", repr)
162 }
163}
164
165fn dot(s: &mut &str) -> PResult<Op> {
166 ".".map(|_| Op::Dot).parse_next(s)
167}
168
169fn name_str(s: &mut &str) -> PResult<String> {
170 alphanumeric1.map(|s: &str| s.to_string()).parse_next(s)
171}
172
173fn name(s: &mut &str) -> PResult<Op> {
174 name_str.map(|name| Op::Name(name)).parse_next(s)
175}
176
177fn quoted_name(s: &mut &str) -> PResult<String> {
178 delimited("\"", name_str, "\"").parse_next(s)
179}
180
181fn comma_space(s: &mut &str) -> PResult<()> {
182 let _ = ",".parse_next(s)?;
183 let _ = space0.parse_next(s)?;
184 Ok(())
185}
186
187fn space_colon_space(s: &mut &str) -> PResult<()> {
188 let _ = space0.parse_next(s)?;
189 let _ = ":".parse_next(s)?;
190 let _ = space0.parse_next(s)?;
191 Ok(())
192}
193
194fn bracket_name_list(s: &mut &str) -> PResult<Op> {
195 let list = separated(1.., quoted_name, comma_space)
196 .map(|list| Op::BracketName(list))
197 .parse_next(s)?;
198 let _ = opt(comma_space).parse_next(s)?;
200 Ok(list)
201}
202
203fn bracket_index_list(s: &mut &str) -> PResult<(Op)> {
204 let list = separated(1.., index, comma_space)
205 .map(|list| Op::BracketIndex(list))
206 .parse_next(s)?;
207 let _ = opt(comma_space).parse_next(s)?;
209 Ok(list)
210}
211
212fn open_bracket_space(s: &mut &str) -> PResult<()> {
213 let _ = "[".parse_next(s)?;
214 let _ = space0.parse_next(s)?;
215 Ok(())
216}
217
218fn close_bracket_space(s: &mut &str) -> PResult<()> {
219 let _ = "]".parse_next(s)?;
220 let _ = space0.parse_next(s)?;
221 Ok(())
222}
223
224fn bracket(s: &mut &str) -> PResult<Op> {
225 delimited(
226 open_bracket_space,
227 alt((bracket_index_list, bracket_name_list)),
228 close_bracket_space,
229 )
230 .parse_next(s)
231}
232
233pub fn op(s: &mut &str) -> PResult<Op> {
234 alt((dot, name, bracket)).parse_next(s)
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use pretty_assertions::assert_eq;
241
242 macro_rules! s {
243 ($literal:expr) => {
244 String::from($literal)
245 };
246 }
247
248 #[test]
251 fn test_positive_number() {
252 let mut input = "1";
253 }
254
255 #[test]
256 fn test_zero() {
257 let mut input = "0";
258 let expected = Ok(0);
259 let result = number(&mut input);
260 assert_eq!(expected, result);
261 assert_eq!("", input);
262 }
263
264 #[test]
265 fn test_negative_number() {
266 let mut input = "-1";
267 let expected = Ok(-1);
268 let result = number(&mut input);
269 assert_eq!(expected, result);
270 assert_eq!("", input);
271 }
272
273 #[test]
274 fn test_space_colon_space_1() {
275 let mut input = ":";
276 let result = space_colon_space(&mut input);
277 assert_eq!(Ok(()), result);
278 }
279
280 #[test]
281 fn test_space_colon_space_2() {
282 let mut input = " :";
283 let result = space_colon_space(&mut input);
284 assert_eq!(Ok(()), result);
285 }
286
287 #[test]
288 fn test_space_colon_space_3() {
289 let mut input = ": ";
290 let result = space_colon_space(&mut input);
291 assert_eq!(Ok(()), result);
292 }
293
294 #[test]
295 fn test_space_colon_space_4() {
296 let mut input = " : ";
297 let result = space_colon_space(&mut input);
298 assert_eq!(Ok(()), result);
299 }
300
301 #[test]
302 fn test_range() {
303 let mut input = "1:3";
304 let expected = Ok(Range { start: 1, end: 3 });
305 let result = range(&mut input);
306 assert_eq!(expected, result);
307 assert_eq!("", input);
308 }
309
310 #[test]
311 fn test_bracket_range_list_one_item() {
312 let mut input = "1:4";
313 let expected = Ok(Op::BracketIndex(vec![Index::Range(Range::new(1, 4))]));
314 let result = bracket_index_list(&mut input);
315 assert_eq!(expected, result);
316 assert_eq!("", input);
317 }
318
319 #[test]
320 fn test_bracket_range_list_one_item_trailing_comma() {
321 let mut input = "1:4,";
322 let expected = Ok(Op::BracketIndex(vec![Index::Range(Range::new(1, 4))]));
323 let result = bracket_index_list(&mut input);
324 assert_eq!(expected, result);
325 assert_eq!("", input);
326 }
327
328 #[test]
329 fn test_bracket_range_list_multiple_items() {
330 let mut input = "1:2, 2:3, 3, 4";
331 let expected = Ok(Op::BracketIndex(vec![
332 Index::Range(Range::new(1, 2)),
333 Index::Range(Range::new(2, 3)),
334 Index::Number(3),
335 Index::Number(4),
336 ]));
337 let result = bracket_index_list(&mut input);
338 assert_eq!(expected, result);
339 assert_eq!("", input);
340 }
341
342 #[test]
343 fn test_bracket_range_list_no_space() {
344 let mut input = "1:1,2:2,3:3";
345 let expected = Ok(Op::BracketIndex(vec![
346 Index::Range(Range::new(1, 1)),
347 Index::Range(Range::new(2, 2)),
348 Index::Range(Range::new(3, 3)),
349 ]));
350 let result = bracket_index_list(&mut input);
351 assert_eq!(expected, result);
352 assert_eq!("", input);
353 }
354
355 #[test]
356 fn test_bracket_range_list_trailing_comma() {
357 let mut input = "0:1,1:2,2:3,";
358 let expected = Ok(Op::BracketIndex(vec![
359 Index::Range(Range::new(0, 1)),
360 Index::Range(Range::new(1, 2)),
361 Index::Range(Range::new(2, 3)),
362 ]));
363 let result = bracket_index_list(&mut input);
364 assert_eq!(expected, result);
365 assert_eq!("", input);
366 }
367
368 #[test]
369 fn test_bracket_range_list_negatives() {
370 let mut input = "0:1, 0:-2,-2, -3";
371 let expected = Ok(Op::BracketIndex(vec![
372 Index::Range(Range::new(0, 1)),
373 Index::Range(Range::new(0, -2)),
374 Index::Number(-2),
375 Index::Number(-3),
376 ]));
377 let result = bracket_index_list(&mut input);
378 assert_eq!(expected, result);
379 assert_eq!("", input);
380 }
381
382 #[test]
383 fn test_bracket_num_list_one_item() {
384 let mut input = "1";
385 let expected = Ok(Op::BracketIndex(vec![Index::Number(1)]));
386 let result = bracket_index_list(&mut input);
387 assert_eq!(expected, result);
388 assert_eq!("", input);
389 }
390
391 #[test]
392 fn test_bracket_num_list_one_item_trailing_comma() {
393 let mut input = "1,";
394 let expected = Ok(Op::BracketIndex(vec![Index::Number(1)]));
395 let result = bracket_index_list(&mut input);
396 assert_eq!(expected, result);
397 assert_eq!("", input);
398 }
399
400 #[test]
401 fn test_bracket_num_list_multiple_items() {
402 let mut input = "1, 2, 3";
403 let expected = Ok(Op::BracketIndex(vec![
404 Index::Number(1),
405 Index::Number(2),
406 Index::Number(3),
407 ]));
408 let result = bracket_index_list(&mut input);
409 assert_eq!(expected, result);
410 assert_eq!("", input);
411 }
412
413 #[test]
414 fn test_bracket_num_list_no_space() {
415 let mut input = "1,2,3";
416 let expected = Ok(Op::BracketIndex(vec![
417 Index::Number(1),
418 Index::Number(2),
419 Index::Number(3),
420 ]));
421 let result = bracket_index_list(&mut input);
422 assert_eq!(expected, result);
423 assert_eq!("", input);
424 }
425
426 #[test]
427 fn test_bracket_num_list_trailing_comma() {
428 let mut input = "1,2,3,";
429 let expected = Ok(Op::BracketIndex(vec![
430 Index::Number(1),
431 Index::Number(2),
432 Index::Number(3),
433 ]));
434 let result = bracket_index_list(&mut input);
435 assert_eq!(expected, result);
436 assert_eq!("", input);
437 }
438
439 #[test]
440 fn test_bracket_num_list_negatives() {
441 let mut input = "1, -2,-3";
442 let expected = Ok(Op::BracketIndex(vec![
443 Index::Number(1),
444 Index::Number(-2),
445 Index::Number(-3),
446 ]));
447 let result = bracket_index_list(&mut input);
448 assert_eq!(expected, result);
449 assert_eq!("", input);
450 }
451
452 #[test]
453 fn test_bracket_name_list_one_item() {
454 let mut input = "\"1\"";
455 let expected = Ok(Op::BracketName(vec![s!("1")]));
456 let result = bracket_name_list(&mut input);
457 assert_eq!(expected, result);
458 assert_eq!("", input);
459 }
460
461 #[test]
462 fn test_bracket_name_list_one_item_trailing_comma() {
463 let mut input = "\"1\",";
464 let expected = Ok(Op::BracketName(vec![s!("1")]));
465 let result = bracket_name_list(&mut input);
466 assert_eq!(expected, result);
467 assert_eq!("", input);
468 }
469
470 #[test]
471 fn test_bracket_name_list_multiple_items() {
472 let mut input = "\"1\", \"2\", \"3\"";
473 let expected = Ok(Op::BracketName(vec![s!("1"), s!("2"), s!("3")]));
474 let result = bracket_name_list(&mut input);
475 assert_eq!(expected, result);
476 assert_eq!("", input);
477 }
478
479 #[test]
480 fn test_bracket_name_list_no_space() {
481 let mut input = "\"1\",\"2\",\"3\"";
482 let expected = Ok(Op::BracketName(vec![s!("1"), s!("2"), s!("3")]));
483 let result = bracket_name_list(&mut input);
484 assert_eq!(expected, result);
485 assert_eq!("", input);
486 }
487
488 #[test]
489 fn test_bracket_name_list_trailing_comma() {
490 let mut input = "\"1\",\"2\",\"3\",";
491 let expected = Ok(Op::BracketName(vec![s!("1"), s!("2"), s!("3")]));
492 let result = bracket_name_list(&mut input);
493 assert_eq!(expected, result);
494 assert_eq!("", input);
495 }
496
497 #[test]
498 fn test_op_dot() {
499 let mut input = ".";
500 let expected = Ok(Op::Dot);
501 let result = op(&mut input);
502 assert_eq!(expected, result);
503 assert_eq!("", input);
504 }
505
506 #[test]
507 fn test_op_name() {
508 let mut input = "name";
509 let expected = Ok(Op::Name(String::from("name")));
510 let result = op(&mut input);
511 assert_eq!(expected, result);
512 assert_eq!("", input);
513 }
514
515 #[test]
516 fn test_op_bracket_name_list() {
517 let mut input = "[\"name\"]";
518 let expected = Ok(Op::BracketName(vec![String::from("name")]));
519 let result = op(&mut input);
520 assert_eq!(expected, result);
521 assert_eq!("", input);
522 }
523 #[test]
524 fn test_op_bracket_num_list() {
525 let mut input = "[1, 2, 3]";
526 let expected = Ok(Op::BracketIndex(vec![
527 Index::Number(1),
528 Index::Number(2),
529 Index::Number(3),
530 ]));
531 let result = op(&mut input);
532 assert_eq!(expected, result);
533 assert_eq!("", input);
534 }
535
536 #[test]
537 fn test_op_bracket_range() {
538 let mut input = "[1:4]";
539 let expected = Ok(Op::BracketIndex(vec![Index::Range(Range {
540 start: 1,
541 end: 4,
542 })]));
543 let result = op(&mut input);
544 assert_eq!(expected, result);
545 assert_eq!("", input);
546 }
547}