Skip to main content

toml_edit/parser/
array.rs

1use crate::parser::inline_table::on_inline_table;
2use crate::parser::value::on_scalar;
3use crate::{Array, RawString, Value};
4
5use crate::parser::prelude::*;
6
7/// ```abnf
8/// ;; Array
9///
10/// array = array-open array-values array-close
11/// array-values =  ws-comment-newline val ws-comment-newline array-sep array-values
12/// array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ]
13/// ```
14pub(crate) fn on_array(
15    open_event: &toml_parser::parser::Event,
16    input: &mut Input<'_>,
17    source: toml_parser::Source<'_>,
18    errors: &mut dyn ErrorSink,
19) -> Value {
20    #[cfg(feature = "debug")]
21    let _scope = TraceScope::new("array::on_array");
22    let mut result = Array::new();
23    let mut close_span = open_event.span();
24
25    let mut state = State::default();
26    state.open(open_event);
27    while let Some(event) = input.next_token() {
28        close_span = event.span();
29        match event.kind() {
30            EventKind::StdTableOpen
31            | EventKind::ArrayTableOpen
32            | EventKind::InlineTableClose
33            | EventKind::SimpleKey
34            | EventKind::KeySep
35            | EventKind::KeyValSep
36            | EventKind::StdTableClose
37            | EventKind::ArrayTableClose => {
38                #[cfg(feature = "debug")]
39                trace(
40                    &format!("unexpected {event:?}"),
41                    anstyle::AnsiColor::Red.on_default(),
42                );
43                break;
44            }
45            EventKind::Error => {
46                #[cfg(feature = "debug")]
47                trace(
48                    &format!("unexpected {event:?}"),
49                    anstyle::AnsiColor::Red.on_default(),
50                );
51                continue;
52            }
53            EventKind::InlineTableOpen => {
54                let value = on_inline_table(event, input, source, errors);
55                state.capture_value(event, value);
56            }
57            EventKind::ArrayOpen => {
58                let value = on_array(event, input, source, errors);
59                state.capture_value(event, value);
60            }
61            EventKind::Scalar => {
62                let value = on_scalar(event, source, errors);
63                state.capture_value(event, value);
64            }
65            EventKind::ValueSep => {
66                state.finish_value(event, &mut result);
67                state.sep_value(event);
68            }
69            EventKind::Whitespace | EventKind::Comment | EventKind::Newline => {
70                state.whitespace(event);
71            }
72            EventKind::ArrayClose => {
73                state.finish_value(event, &mut result);
74                state.close(open_event, event, &mut result);
75                break;
76            }
77        }
78    }
79    if result.span.is_none() {
80        result.span = Some(open_event.span().start()..close_span.end());
81    }
82
83    Value::Array(result)
84}
85
86#[derive(Default)]
87struct State {
88    current_prefix: Option<toml_parser::Span>,
89    current_value: Option<Value>,
90    trailing_start: Option<usize>,
91    current_suffix: Option<toml_parser::Span>,
92}
93
94impl State {
95    fn open(&mut self, open_event: &toml_parser::parser::Event) {
96        self.trailing_start = Some(open_event.span().end());
97    }
98
99    fn whitespace(&mut self, event: &toml_parser::parser::Event) {
100        let decor = if self.is_prefix() {
101            self.current_prefix.get_or_insert(event.span())
102        } else {
103            self.current_suffix.get_or_insert(event.span())
104        };
105        *decor = decor.append(event.span());
106    }
107
108    fn is_prefix(&self) -> bool {
109        self.current_value.is_none()
110    }
111
112    fn capture_value(&mut self, event: &toml_parser::parser::Event, value: Value) {
113        self.trailing_start = None;
114        self.current_prefix
115            .get_or_insert_with(|| event.span().before());
116        self.current_value = Some(value);
117    }
118
119    fn finish_value(&mut self, event: &toml_parser::parser::Event, result: &mut Array) {
120        #[cfg(feature = "debug")]
121        let _scope = TraceScope::new("array::finish_value");
122        if let Some(mut value) = self.current_value.take() {
123            let prefix = self
124                .current_prefix
125                .take()
126                .expect("setting a value should set a prefix");
127            let suffix = self
128                .current_suffix
129                .take()
130                .unwrap_or_else(|| event.span().before());
131            let decor = value.decor_mut();
132            decor.set_prefix(RawString::with_span(prefix.start()..prefix.end()));
133            decor.set_suffix(RawString::with_span(suffix.start()..suffix.end()));
134            result.push_formatted(value);
135        }
136    }
137
138    fn sep_value(&mut self, event: &toml_parser::parser::Event) {
139        self.trailing_start = Some(event.span().end());
140    }
141
142    fn close(
143        &mut self,
144        open_event: &toml_parser::parser::Event,
145        close_event: &toml_parser::parser::Event,
146        result: &mut Array,
147    ) {
148        #[cfg(feature = "debug")]
149        let _scope = TraceScope::new("array::close");
150        let trailing_comma = self.trailing_start.is_some() && !result.is_empty();
151        let span = open_event.span().append(close_event.span());
152        let trailing_start = self
153            .trailing_start
154            .unwrap_or_else(|| close_event.span().start());
155        let trailing_end = close_event.span().start();
156
157        result.set_trailing_comma(trailing_comma);
158        result.set_trailing(RawString::with_span(trailing_start..trailing_end));
159        result.span = Some(span.start()..span.end());
160    }
161}