use std::iter::FromIterator;
use indexmap::map::IndexMap;
use crate::key::Key;
use crate::repr::{Decor, InternalString};
use crate::value::DEFAULT_VALUE_DECOR;
use crate::{InlineTable, Item, Value};
#[derive(Clone, Debug, Default)]
pub struct Table {
pub(crate) decor: Decor,
pub(crate) implicit: bool,
pub(crate) dotted: bool,
pub(crate) position: Option<usize>,
pub(crate) items: KeyValuePairs,
}
impl Table {
pub fn new() -> Self {
Default::default()
}
pub(crate) fn with_pos(position: Option<usize>) -> Self {
Self {
position,
..Default::default()
}
}
pub fn into_inline_table(mut self) -> InlineTable {
for (_, kv) in self.items.iter_mut() {
kv.value.make_value();
}
InlineTable::with_pairs(self.items)
}
}
impl Table {
pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
let mut values = Vec::new();
let root = Vec::new();
self.get_values_internal(&root, &mut values);
values
}
fn get_values_internal<'s, 'c>(
&'s self,
parent: &[&'s Key],
values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>,
) {
for value in self.items.values() {
let mut path = parent.to_vec();
path.push(&value.key);
match &value.value {
Item::Table(table) if table.is_dotted() => {
table.get_values_internal(&path, values);
}
Item::Value(value) => {
values.push((path, value));
}
_ => {}
}
}
}
pub fn fmt(&mut self) {
decorate_table(self);
}
pub fn sort_values(&mut self) {
self.items.sort_keys();
for kv in self.items.values_mut() {
match &mut kv.value {
Item::Table(table) if table.is_dotted() => {
table.sort_values();
}
_ => {}
}
}
}
pub fn set_implicit(&mut self, implicit: bool) {
self.implicit = implicit;
}
pub fn is_implicit(&self) -> bool {
self.implicit
}
pub fn set_dotted(&mut self, yes: bool) {
self.dotted = yes;
}
pub fn is_dotted(&self) -> bool {
self.dotted
}
pub fn set_position(&mut self, position: usize) {
self.position = Some(position);
}
pub fn position(&self) -> Option<usize> {
self.position
}
pub fn decor_mut(&mut self) -> &mut Decor {
&mut self.decor
}
pub fn decor(&self) -> &Decor {
&self.decor
}
pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
self.items.get_mut(key).map(|kv| &mut kv.key.decor)
}
pub fn key_decor(&self, key: &str) -> Option<&Decor> {
self.items.get(key).map(|kv| &kv.key.decor)
}
}
impl Table {
pub fn iter(&self) -> Iter<'_> {
Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value)))
}
pub fn iter_mut(&mut self) -> IterMut<'_> {
Box::new(
self.items
.iter_mut()
.map(|(key, kv)| (&key[..], &mut kv.value)),
)
}
pub fn len(&self) -> usize {
self.items.iter().filter(|i| !(i.1).value.is_none()).count()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) {
self.items.clear()
}
pub fn entry<'a>(&'a mut self, key: &str) -> Entry<'a> {
match self.items.entry(key.to_owned()) {
indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, key: None }),
}
}
pub fn entry_format<'a>(&'a mut self, key: &'a Key) -> Entry<'a> {
match self.items.entry(key.get().to_owned()) {
indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
entry,
key: Some(key),
}),
}
}
pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> {
self.items.get(key).map(|kv| &kv.value)
}
pub fn get_mut<'a>(&'a mut self, key: &str) -> Option<&'a mut Item> {
self.items.get_mut(key).map(|kv| &mut kv.value)
}
pub fn contains_key(&self, key: &str) -> bool {
if let Some(kv) = self.items.get(key) {
!kv.value.is_none()
} else {
false
}
}
pub fn contains_table(&self, key: &str) -> bool {
if let Some(kv) = self.items.get(key) {
kv.value.is_table()
} else {
false
}
}
pub fn contains_value(&self, key: &str) -> bool {
if let Some(kv) = self.items.get(key) {
kv.value.is_value()
} else {
false
}
}
pub fn contains_array_of_tables(&self, key: &str) -> bool {
if let Some(kv) = self.items.get(key) {
kv.value.is_array_of_tables()
} else {
false
}
}
pub fn insert(&mut self, key: &str, item: Item) -> Option<Item> {
let kv = TableKeyValue::new(Key::new(key), item);
self.items.insert(key.to_owned(), kv).map(|kv| kv.value)
}
pub fn insert_formatted(&mut self, key: &Key, item: Item) -> Option<Item> {
let kv = TableKeyValue::new(key.to_owned(), item);
self.items
.insert(key.get().to_owned(), kv)
.map(|kv| kv.value)
}
pub fn remove(&mut self, key: &str) -> Option<Item> {
self.items.shift_remove(key).map(|kv| kv.value)
}
pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Item)> {
self.items.shift_remove(key).map(|kv| (kv.key, kv.value))
}
}
impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for Table {
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
for (key, value) in iter {
let key = key.into();
let value = Item::Value(value.into());
let value = TableKeyValue::new(key, value);
self.items.insert(value.key.get().to_owned(), value);
}
}
}
impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Table {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
{
let mut table = Table::new();
table.extend(iter);
table
}
}
impl IntoIterator for Table {
type Item = (String, Item);
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
Box::new(self.items.into_iter().map(|(k, kv)| (k, kv.value)))
}
}
impl<'s> IntoIterator for &'s Table {
type Item = (&'s str, &'s Item);
type IntoIter = Iter<'s>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub(crate) type KeyValuePairs = IndexMap<InternalString, TableKeyValue>;
fn decorate_table(table: &mut Table) {
for (key_decor, value) in table
.items
.iter_mut()
.filter(|&(_, ref kv)| kv.value.is_value())
.map(|(_, kv)| (&mut kv.key.decor, kv.value.as_value_mut().unwrap()))
{
*key_decor = Decor::new(DEFAULT_KEY_DECOR.0, DEFAULT_KEY_DECOR.1);
value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1);
}
}
pub(crate) const DEFAULT_KEY_DECOR: (&str, &str) = ("", " ");
pub(crate) const DEFAULT_TABLE_DECOR: (&str, &str) = ("\n", "");
pub(crate) const DEFAULT_KEY_PATH_DECOR: (&str, &str) = ("", "");
#[derive(Debug, Clone)]
pub(crate) struct TableKeyValue {
pub(crate) key: Key,
pub(crate) value: Item,
}
impl TableKeyValue {
pub(crate) fn new(key: Key, value: Item) -> Self {
TableKeyValue { key, value }
}
}
pub type IntoIter = Box<dyn Iterator<Item = (String, Item)>>;
pub type Iter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Item)> + 'a>;
pub type IterMut<'a> = Box<dyn Iterator<Item = (&'a str, &'a mut Item)> + 'a>;
pub trait TableLike {
fn iter(&self) -> Iter<'_>;
fn iter_mut(&mut self) -> IterMut<'_>;
fn len(&self) -> usize {
self.iter().filter(|&(_, v)| !v.is_none()).count()
}
fn is_empty(&self) -> bool {
self.len() == 0
}
fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item>;
fn contains_key(&self, key: &str) -> bool;
fn insert(&mut self, key: &str, value: Item) -> Option<Item>;
fn remove(&mut self, key: &str) -> Option<Item>;
fn get_values(&self) -> Vec<(Vec<&Key>, &Value)>;
fn fmt(&mut self);
fn sort_values(&mut self);
fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor>;
fn key_decor(&self, key: &str) -> Option<&Decor>;
}
impl TableLike for Table {
fn iter(&self) -> Iter<'_> {
self.iter()
}
fn iter_mut(&mut self) -> IterMut<'_> {
self.iter_mut()
}
fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
self.get(key)
}
fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
self.get_mut(key)
}
fn contains_key(&self, key: &str) -> bool {
self.contains_key(key)
}
fn insert(&mut self, key: &str, value: Item) -> Option<Item> {
self.insert(key, value)
}
fn remove(&mut self, key: &str) -> Option<Item> {
self.remove(key)
}
fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
self.get_values()
}
fn fmt(&mut self) {
self.fmt()
}
fn sort_values(&mut self) {
self.sort_values()
}
fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> {
self.key_decor_mut(key)
}
fn key_decor(&self, key: &str) -> Option<&Decor> {
self.key_decor(key)
}
}
pub enum Entry<'a> {
Occupied(OccupiedEntry<'a>),
Vacant(VacantEntry<'a>),
}
impl<'a> Entry<'a> {
pub fn key(&self) -> &str {
match self {
Entry::Occupied(e) => e.key(),
Entry::Vacant(e) => e.key(),
}
}
pub fn or_insert(self, default: Item) -> &'a mut Item {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
pub fn or_insert_with<F: FnOnce() -> Item>(self, default: F) -> &'a mut Item {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
}
pub struct OccupiedEntry<'a> {
entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>,
}
impl<'a> OccupiedEntry<'a> {
pub fn key(&self) -> &str {
self.entry.key().as_str()
}
pub fn get(&self) -> &Item {
&self.entry.get().value
}
pub fn get_mut(&mut self) -> &mut Item {
&mut self.entry.get_mut().value
}
pub fn into_mut(self) -> &'a mut Item {
&mut self.entry.into_mut().value
}
pub fn insert(&mut self, mut value: Item) -> Item {
std::mem::swap(&mut value, &mut self.entry.get_mut().value);
value
}
pub fn remove(self) -> Item {
self.entry.shift_remove().value
}
}
pub struct VacantEntry<'a> {
entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>,
key: Option<&'a Key>,
}
impl<'a> VacantEntry<'a> {
pub fn key(&self) -> &str {
self.entry.key().as_str()
}
pub fn insert(self, value: Item) -> &'a mut Item {
let key = self.key.cloned().unwrap_or_else(|| Key::new(self.key()));
&mut self.entry.insert(TableKeyValue::new(key, value)).value
}
}