Skip to content

Commit

Permalink
feat: Add table-like mutations (toml-rs#197)
Browse files Browse the repository at this point in the history
- `insert` is made safe due to `into_value`
- `iter_mut` is as safe as existing indexing and `get_mut`
- others, like `remove`, are universal
  • Loading branch information
epage authored Sep 12, 2021
1 parent 2ff172e commit 89df63f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
26 changes: 23 additions & 3 deletions src/inline_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::iter::FromIterator;

use crate::key::Key;
use crate::repr::{Decor, InternalString};
use crate::table::{Iter, KeyValuePairs, TableKeyValue, TableLike};
use crate::table::{Iter, IterMut, KeyValuePairs, TableKeyValue, TableLike};
use crate::value::{DEFAULT_TRAILING_VALUE_DECOR, DEFAULT_VALUE_DECOR};
use crate::{Item, Value};

Expand Down Expand Up @@ -239,9 +239,11 @@ impl InlineTable {
}

/// Inserts a key-value pair into the map.
pub fn insert(&mut self, key: &str, value: Value) -> Option<Item> {
pub fn insert(&mut self, key: &str, value: Value) -> Option<Value> {
let kv = TableKeyValue::new(Key::new(key), Item::Value(value));
self.items.insert(key.to_owned(), kv).map(|kv| kv.value)
self.items
.insert(key.to_owned(), kv)
.and_then(|kv| kv.value.into_value().ok())
}

/// Inserts a key-value pair into the map.
Expand Down Expand Up @@ -347,12 +349,30 @@ impl TableLike for InlineTable {
fn iter(&self) -> Iter<'_> {
Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value)))
}
fn iter_mut(&mut self) -> IterMut<'_> {
Box::new(
self.items
.iter_mut()
.map(|(key, kv)| (&key[..], &mut kv.value)),
)
}
fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
self.items.get(key).map(|kv| &kv.value)
}
fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
self.items.get_mut(key).map(|kv| &mut kv.value)
}
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.into_value().unwrap())
.map(Item::Value)
}
fn remove(&mut self, key: &str) -> Option<Item> {
self.remove(key).map(Item::Value)
}

fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> {
self.get_values()
}
Expand Down
9 changes: 9 additions & 0 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ impl Item {
.or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
}

/// Casts `self` to either a table or an inline table.
pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> {
match self {
Item::Table(t) => Some(t as &mut dyn TableLike),
Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike),
_ => None,
}
}

/// Returns true iff `self` is either a table, or an inline table.
pub fn is_table_like(&self) -> bool {
self.as_table_like().is_some()
Expand Down
22 changes: 21 additions & 1 deletion src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ pub type IterMut<'a> = Box<dyn Iterator<Item = (&'a str, &'a mut Item)> + 'a>;
pub trait TableLike {
/// Returns an iterator over key/value pairs.
fn iter(&self) -> Iter<'_>;
/// Returns an mutable iterator over all key/value pairs, including empty.
fn iter_mut(&mut self) -> IterMut<'_>;
/// Returns the number of nonempty items.
fn len(&self) -> usize {
self.iter().filter(|&(_, v)| !v.is_none()).count()
Expand All @@ -406,6 +408,12 @@ pub trait TableLike {
fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
/// Returns an optional mutable reference to an item given the key.
fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item>;
/// Returns true iff the table contains an item with the given key.
fn contains_key(&self, key: &str) -> bool;
/// Inserts a key-value pair into the map.
fn insert(&mut self, key: &str, value: Item) -> Option<Item>;
/// Removes an item given the key.
fn remove(&mut self, key: &str) -> Option<Item>;

/// Get key/values for values that are visually children of this table
///
Expand All @@ -426,16 +434,28 @@ pub trait TableLike {
}

impl TableLike for Table {
/// Returns an iterator over all subitems, including `Item::None`.
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()
}
Expand Down

0 comments on commit 89df63f

Please sign in to comment.