use serde::de::IgnoredAny;
use toml::de::{DeTable, DeValue};
use super::entries::{Entry, Written};
use super::{Input, InputError};
pub(super) fn entries(input: &Input) -> Result<Vec<Entry>, InputError> {
input.parse::<IgnoredAny>()?;
let root = DeTable::parse(&input.text)
.map_err(|error| InputError::whole(input.name.clone(), error.message().to_owned()))?;
let mut entries: Vec<_> = root.get_ref().iter().collect();
entries.sort_by_key(|(key, _)| key.span().start);
Ok(entries
.into_iter()
.map(|(key, value)| {
let span = value.span();
let (written, string) = match value.get_ref() {
DeValue::String(text) => (
string_written(input.text.get(span.clone()).unwrap_or_default()),
Some(text.to_string()),
),
DeValue::Integer(_)
| DeValue::Float(_)
| DeValue::Boolean(_)
| DeValue::Datetime(_) => (Written::Plain, None),
DeValue::Array(_) | DeValue::Table(_) => (Written::Collection, None),
};
Entry {
key: key.get_ref().to_string(),
value: span,
written,
string,
}
})
.collect())
}
fn string_written(text: &str) -> Written {
if text.starts_with("\"\"\"") {
Written::MultilineBasic
} else if text.starts_with("'''") {
Written::MultilineLiteral
} else if text.starts_with('\'') {
Written::SingleQuoted
} else {
Written::DoubleQuoted
}
}