rtoml/bulletins/
array.rs

1use crate::bulletins::num::handle_num;
2use crate::bulletins::string::TomlString;
3use crate::bulletins::TomlValue;
4use crate::bulletins::{get_type, Types};
5use crate::lexer::Tokens;
6use crate::{assert_toml, comp_err};
7use std::iter::Peekable;
8
9pub struct Arr<'a, S: Iterator<Item = Tokens>> {
10    peekable: &'a mut Peekable<S>,
11    arr_type: Option<Types>,
12}
13
14#[derive(Debug)]
15struct TomlArray<T> {
16    array: Vec<T>,
17}
18
19#[macro_use]
20macro_rules! close_or_comma {
21    ( $arr : expr ) => {
22        if let Some(Tokens::Sbc) = $arr.peekable.peek() {
23            break;
24        } else {
25            assert_toml!($arr.peekable.next(), Tokens::Comma);
26        }
27    };
28}
29
30impl<'a, S: Iterator<Item = Tokens>> Arr<'a, S> {
31    pub fn handle(peekable: &mut Peekable<S>) -> TomlValue {
32        // determine the type of the array from the first element,
33        // in toml, array elements can have only a single type
34        let mut arr = Arr {
35            peekable: peekable,
36            arr_type: None,
37        };
38        let mut vec = Vec::new();
39        while arr.peekable.peek().is_some() {
40            if let Some(x) = arr.peekable.next() {
41                match x {
42                    Tokens::DoubleQuote | Tokens::SingleQuote => {
43                        if !arr.has_type() {
44                            arr.set_type(Types::String);
45                            let mut string = TomlValue::String("".to_string());
46                            if x == Tokens::DoubleQuote {
47                                string = TomlString::handle(arr.peekable, 1);
48                            } else {
49                                string = TomlString::handle(arr.peekable, 3)
50                            }
51                            vec.push(string);
52                            close_or_comma!(arr);
53                        } else {
54                            if arr.arr_type == Some(Types::String) {
55                                let mut string = TomlValue::String("".to_string());
56                                if x == Tokens::DoubleQuote {
57                                    string = TomlString::handle(arr.peekable, 1);
58                                } else {
59                                    string = TomlString::handle(arr.peekable, 3)
60                                }
61                                vec.push(string);
62                                close_or_comma!(arr);
63                            } else {
64                                if let Some(x) = arr.peekable.next() {
65                                    panic!(
66                                        "{:?} type found inside a {:?} type array",
67                                        get_type(&x.to_string()),
68                                        arr.arr_type
69                                    );
70                                }
71                            }
72                        }
73                    }
74                    Tokens::Sbo => {
75                        let something = Arr::handle(arr.peekable);
76                        close_or_comma!(arr);
77                    }
78                    // arrays can be spanned to multiple lines
79                    Tokens::LineBreak => (),
80                    _ => {
81                        let type_of_literal = get_type(&x.to_string());
82                        if !arr.has_type() {
83                            arr.set_type(type_of_literal);
84                            match type_of_literal {
85                                Types::String => {
86                                    comp_err!("Unexpected token, expected quotes or number")
87                                }
88                                Types::Int | Types::Floating => {
89                                    let final_num = handle_num(x.to_string());
90                                    vec.push(final_num);
91                                    close_or_comma!(arr);
92                                }
93                                Types::Boolean => {
94                                    vec.push(TomlValue::String(x.to_string()));
95                                    close_or_comma!(arr);
96                                }
97                                _ => (),
98                            }
99                        } else {
100                            let arr_type = arr.arr_type.unwrap();
101                            if type_of_literal == arr_type {
102                                vec.push(TomlValue::String(x.to_string()));
103                                close_or_comma!(arr);
104                            } else {
105                                comp_err!(format!(
106                                    "Found a {:?} type found in a {:?} type array",
107                                    type_of_literal, arr_type
108                                ));
109                            }
110                        }
111                    }
112                }
113            }
114        }
115        assert_toml!(arr.peekable.next(), Tokens::Sbc);
116        TomlValue::Array(vec)
117    }
118
119    pub fn has_type(&self) -> bool {
120        self.arr_type.is_some()
121    }
122    pub fn set_type(&mut self, ele_type: Types) {
123        self.arr_type = Some(ele_type);
124    }
125}