use combine::*;
use combine::char::char;
use combine::primitives::RangeStream;
use parser::errors::CustomError;
use parser::trivia::ws;
use parser::key::key;
use parser::value::value;
use value::InlineTable;
use decor::{InternalString, Repr};
use table::{Item, TableKeyValue};
use formatted::decorated;
parse!(inline_table() -> InlineTable, {
between(char(INLINE_TABLE_OPEN), char(INLINE_TABLE_CLOSE),
inline_table_keyvals().and_then(|(p, v)| table_from_pairs(p, v)))
});
fn table_from_pairs(
preamble: &str,
v: Vec<(InternalString, TableKeyValue)>,
) -> Result<InlineTable, CustomError> {
let mut table = InlineTable::default();
table.preamble = InternalString::from(preamble);
for (k, kv) in v {
if table.contains_key(&k) {
return Err(CustomError::DuplicateKey {
key: k,
table: "inline".into(),
});
}
table.items.insert(k, kv);
}
Ok(table)
}
const INLINE_TABLE_OPEN: char = '{';
const INLINE_TABLE_CLOSE: char = '}';
const INLINE_TABLE_SEP: char = ',';
pub(crate) const KEYVAL_SEP: char = '=';
parse!(inline_table_keyvals() -> (&'a str, Vec<(InternalString, TableKeyValue)>), {
(
sep_by(keyval(), char(INLINE_TABLE_SEP)),
ws(),
).map(|(v, w)| {
(w, v)
})
});
parse!(keyval() -> (InternalString, TableKeyValue), {
(
try((ws(), key(), ws())),
char(KEYVAL_SEP),
(ws(), value(), ws()),
).map(|(k, _, v)| {
let (pre, v, suf) = v;
let v = decorated(v, pre, suf);
let (pre, (raw, key), suf) = k;
(
key,
TableKeyValue {
key: Repr::new(pre, raw, suf),
value: Item::Value(v),
}
)
})
});