toml_edit/parser/
array.rs1use crate::parser::inline_table::on_inline_table;
2use crate::parser::value::on_scalar;
3use crate::{Array, RawString, Value};
4
5use crate::parser::prelude::*;
6
7pub(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}