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