Skip to main content

toml_edit/parser/
value.rs

1use crate::RawString;
2use crate::Value;
3use crate::parser::array::on_array;
4use crate::parser::inline_table::on_inline_table;
5use crate::parser::prelude::*;
6use crate::repr::{Formatted, Repr};
7
8/// ```abnf
9/// val = string / boolean / array / inline-table / date-time / float / integer
10/// ```
11pub(crate) fn value(
12    input: &mut Input<'_>,
13    source: toml_parser::Source<'_>,
14    errors: &mut dyn ErrorSink,
15) -> Value {
16    #[cfg(feature = "debug")]
17    let _scope = TraceScope::new("value");
18    if let Some(event) = input.next_token() {
19        match event.kind() {
20            EventKind::StdTableOpen
21            | EventKind::ArrayTableOpen
22            | EventKind::InlineTableClose
23            | EventKind::ArrayClose
24            | EventKind::ValueSep
25            | EventKind::Comment
26            | EventKind::Newline
27            | EventKind::Error
28            | EventKind::SimpleKey
29            | EventKind::KeySep
30            | EventKind::KeyValSep
31            | EventKind::StdTableClose
32            | EventKind::ArrayTableClose => {
33                #[cfg(feature = "debug")]
34                trace(
35                    &format!("unexpected {event:?}"),
36                    anstyle::AnsiColor::Red.on_default(),
37                );
38            }
39            EventKind::Whitespace => {
40                #[cfg(feature = "debug")]
41                trace(
42                    &format!("unexpected {event:?}"),
43                    anstyle::AnsiColor::Red.on_default(),
44                );
45            }
46            EventKind::InlineTableOpen => {
47                return on_inline_table(event, input, source, errors);
48            }
49            EventKind::ArrayOpen => {
50                return on_array(event, input, source, errors);
51            }
52            EventKind::Scalar => {
53                return on_scalar(event, source, errors);
54            }
55        }
56    }
57
58    let value_raw = RawString::with_span(0..0);
59    let mut f = Formatted::new(0);
60    f.set_repr_unchecked(Repr::new_unchecked(value_raw));
61    Value::Integer(f)
62}
63
64pub(crate) fn on_scalar(
65    event: &toml_parser::parser::Event,
66    source: toml_parser::Source<'_>,
67    errors: &mut dyn ErrorSink,
68) -> Value {
69    #[cfg(feature = "debug")]
70    let _scope = TraceScope::new("on_scalar");
71    let value_span = event.span();
72    let value_raw = RawString::with_span(value_span.start()..value_span.end());
73
74    let raw = source.get(event).unwrap();
75    let mut decoded = std::borrow::Cow::Borrowed("");
76    let kind = raw.decode_scalar(&mut decoded, errors);
77    match kind {
78        toml_parser::decoder::ScalarKind::String => {
79            let mut f = Formatted::new(decoded.into());
80            f.set_repr_unchecked(Repr::new_unchecked(value_raw));
81            Value::String(f)
82        }
83        toml_parser::decoder::ScalarKind::Boolean(value) => {
84            let mut f = Formatted::new(value);
85            f.set_repr_unchecked(Repr::new_unchecked(value_raw));
86            Value::Boolean(f)
87        }
88        toml_parser::decoder::ScalarKind::DateTime => {
89            let value = match decoded.parse::<toml_datetime::Datetime>() {
90                Ok(value) => value,
91                Err(err) => {
92                    errors.report_error(
93                        ParseError::new(err.to_string()).with_unexpected(event.span()),
94                    );
95                    toml_datetime::Datetime {
96                        date: None,
97                        time: None,
98                        offset: None,
99                    }
100                }
101            };
102            let mut f = Formatted::new(value);
103            f.set_repr_unchecked(Repr::new_unchecked(value_raw));
104            Value::Datetime(f)
105        }
106        toml_parser::decoder::ScalarKind::Float => {
107            let value = match decoded.parse::<f64>() {
108                Ok(value) => {
109                    if value.is_infinite()
110                        && !(decoded
111                            .strip_prefix(['+', '-'])
112                            .unwrap_or(&decoded)
113                            .chars()
114                            .all(|c| c.is_ascii_alphabetic()))
115                    {
116                        errors.report_error(
117                            ParseError::new("floating-point number overflowed")
118                                .with_unexpected(event.span()),
119                        );
120                    }
121                    value
122                }
123                Err(_) => {
124                    errors.report_error(
125                        ParseError::new(kind.invalid_description()).with_unexpected(event.span()),
126                    );
127                    f64::NAN
128                }
129            };
130            let mut f = Formatted::new(value);
131            f.set_repr_unchecked(Repr::new_unchecked(value_raw));
132            Value::Float(f)
133        }
134        toml_parser::decoder::ScalarKind::Integer(radix) => {
135            let value = match i64::from_str_radix(&decoded, radix.value()) {
136                Ok(value) => value,
137                Err(_) => {
138                    // Assuming the decoder fully validated it, leaving only overflow errors
139                    errors.report_error(
140                        ParseError::new("integer number overflowed").with_unexpected(event.span()),
141                    );
142                    i64::MAX
143                }
144            };
145            let mut f = Formatted::new(value);
146            f.set_repr_unchecked(Repr::new_unchecked(value_raw));
147            Value::Integer(f)
148        }
149    }
150}