diff --git a/Cargo.lock b/Cargo.lock index 1422403b..0351053e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,9 +366,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown", diff --git a/crates/toml_edit/Cargo.toml b/crates/toml_edit/Cargo.toml index cd46f28a..dcc401e0 100644 --- a/crates/toml_edit/Cargo.toml +++ b/crates/toml_edit/Cargo.toml @@ -40,7 +40,7 @@ serde = ["dep:serde", "toml_datetime/serde", "dep:serde_spanned"] unbounded = [] [dependencies] -indexmap = { version = "2.0.0", features = ["std"] } +indexmap = { version = "2.3.0", features = ["std"] } winnow = { version = "0.6.18", optional = true } serde = { version = "1.0.145", optional = true } kstring = { version = "2.0.0", features = ["max_inline"], optional = true } diff --git a/crates/toml_edit/src/de/key.rs b/crates/toml_edit/src/de/key.rs index d7ce30e4..7536078f 100644 --- a/crates/toml_edit/src/de/key.rs +++ b/crates/toml_edit/src/de/key.rs @@ -4,11 +4,11 @@ use super::Error; pub(crate) struct KeyDeserializer { span: Option>, - key: crate::InternalString, + key: crate::Key, } impl KeyDeserializer { - pub(crate) fn new(key: crate::InternalString, span: Option>) -> Self { + pub(crate) fn new(key: crate::Key, span: Option>) -> Self { KeyDeserializer { span, key } } } @@ -56,7 +56,7 @@ impl<'de> serde::de::Deserializer<'de> for KeyDeserializer { { if serde_spanned::__unstable::is_spanned(name, fields) { if let Some(span) = self.span.clone() { - return visitor.visit_map(super::SpannedDeserializer::new(self.key.as_str(), span)); + return visitor.visit_map(super::SpannedDeserializer::new(self.key.get(), span)); } } self.deserialize_any(visitor) diff --git a/crates/toml_edit/src/de/mod.rs b/crates/toml_edit/src/de/mod.rs index 391153f0..fe1d285a 100644 --- a/crates/toml_edit/src/de/mod.rs +++ b/crates/toml_edit/src/de/mod.rs @@ -292,10 +292,10 @@ pub(crate) fn validate_struct_keys( fields: &'static [&'static str], ) -> Result<(), Error> { let extra_fields = table - .iter() - .filter_map(|(key, val)| { - if !fields.contains(&key.as_str()) { - Some(val.clone()) + .keys() + .filter_map(|key| { + if !fields.contains(&key.get()) { + Some(key.clone()) } else { None } @@ -310,12 +310,12 @@ pub(crate) fn validate_struct_keys( "unexpected keys in table: {}, available keys: {}", extra_fields .iter() - .map(|k| k.key.get()) + .map(|k| k.get()) .collect::>() .join(", "), fields.join(", "), ), - extra_fields[0].key.span(), + extra_fields[0].span(), )) } } diff --git a/crates/toml_edit/src/de/table.rs b/crates/toml_edit/src/de/table.rs index 85adcc03..436d17a3 100644 --- a/crates/toml_edit/src/de/table.rs +++ b/crates/toml_edit/src/de/table.rs @@ -116,7 +116,7 @@ impl crate::InlineTable { } pub(crate) struct TableMapAccess { - iter: indexmap::map::IntoIter, + iter: indexmap::map::IntoIter, span: Option>, value: Option<(crate::Key, crate::Item)>, } @@ -140,16 +140,17 @@ impl<'de> serde::de::MapAccess<'de> for TableMapAccess { { match self.iter.next() { Some((k, v)) => { + let key_span = k.span(); let ret = seed - .deserialize(super::KeyDeserializer::new(k, v.key.span())) + .deserialize(super::KeyDeserializer::new(k.clone(), key_span.clone())) .map(Some) .map_err(|mut e: Self::Error| { if e.span().is_none() { - e.set_span(v.key.span()); + e.set_span(key_span); } e }); - self.value = Some((v.key, v.value)); + self.value = Some((k, v)); ret } None => Ok(None), @@ -201,12 +202,12 @@ impl<'de> serde::de::EnumAccess<'de> for TableMapAccess { .deserialize(key.into_deserializer()) .map_err(|mut e: Self::Error| { if e.span().is_none() { - e.set_span(value.key.span()); + e.set_span(key.span()); } e })?; - let variant = super::TableEnumDeserializer::new(value.value); + let variant = super::TableEnumDeserializer::new(value); Ok((val, variant)) } diff --git a/crates/toml_edit/src/de/table_enum.rs b/crates/toml_edit/src/de/table_enum.rs index 0ceeab62..8c3433f4 100644 --- a/crates/toml_edit/src/de/table_enum.rs +++ b/crates/toml_edit/src/de/table_enum.rs @@ -101,19 +101,13 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { .items .into_iter() .enumerate() - .map( - |(index, (_, value))| match value.key.get().parse::() { - Ok(key_index) if key_index == index => Ok(value.value), - Ok(_) | Err(_) => Err(Error::custom( - format!( - "expected table key `{}`, but was `{}`", - index, - value.key.get() - ), - value.key.span(), - )), - }, - ) + .map(|(index, (key, value))| match key.get().parse::() { + Ok(key_index) if key_index == index => Ok(value), + Ok(_) | Err(_) => Err(Error::custom( + format!("expected table key `{}`, but was `{}`", index, key.get()), + key.span(), + )), + }) .collect(); let tuple_values = tuple_values?; @@ -135,19 +129,13 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { .items .into_iter() .enumerate() - .map( - |(index, (_, value))| match value.key.get().parse::() { - Ok(key_index) if key_index == index => Ok(value.value), - Ok(_) | Err(_) => Err(Error::custom( - format!( - "expected table key `{}`, but was `{}`", - index, - value.key.get() - ), - value.key.span(), - )), - }, - ) + .map(|(index, (key, value))| match key.get().parse::() { + Ok(key_index) if key_index == index => Ok(value), + Ok(_) | Err(_) => Err(Error::custom( + format!("expected table key `{}`, but was `{}`", index, key.get()), + key.span(), + )), + }) .collect(); let tuple_values = tuple_values?; diff --git a/crates/toml_edit/src/encode.rs b/crates/toml_edit/src/encode.rs index b45f0e34..54319c4a 100644 --- a/crates/toml_edit/src/encode.rs +++ b/crates/toml_edit/src/encode.rs @@ -237,17 +237,17 @@ where callback(table, path, is_array_of_tables)?; } - for kv in table.items.values() { - match kv.value { + for (key, value) in table.items.iter() { + match value { Item::Table(ref t) => { - let key = kv.key.clone(); + let key = key.clone(); path.push(key); visit_nested_tables(t, path, false, callback)?; path.pop(); } Item::ArrayOfTables(ref a) => { for t in a.iter() { - let key = kv.key.clone(); + let key = key.clone(); path.push(key); visit_nested_tables(t, path, true, callback)?; path.pop(); diff --git a/crates/toml_edit/src/index.rs b/crates/toml_edit/src/index.rs index cdf646fd..35dcc146 100644 --- a/crates/toml_edit/src/index.rs +++ b/crates/toml_edit/src/index.rs @@ -1,9 +1,8 @@ use std::ops; use crate::key::Key; -use crate::table::TableKeyValue; use crate::DocumentMut; -use crate::{value, InlineTable, InternalString, Item, Table, Value}; +use crate::{value, InlineTable, Item, Table, Value}; // copied from // https://github.com/serde-rs/json/blob/master/src/value/index.rs @@ -39,34 +38,21 @@ impl Index for str { Item::Value(ref v) => v .as_inline_table() .and_then(|t| t.items.get(self)) - .and_then(|kv| { - if !kv.value.is_none() { - Some(&kv.value) - } else { - None - } - }), + .and_then(|value| if !value.is_none() { Some(value) } else { None }), _ => None, } } fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> { if let Item::None = *v { let mut t = InlineTable::default(); - t.items.insert( - InternalString::from(self), - TableKeyValue::new(Key::new(self), Item::None), - ); + t.items.insert(Key::new(self), Item::None); *v = value(Value::InlineTable(t)); } match *v { Item::Table(ref mut t) => Some(t.entry(self).or_insert(Item::None)), - Item::Value(ref mut v) => v.as_inline_table_mut().map(|t| { - &mut t - .items - .entry(InternalString::from(self)) - .or_insert_with(|| TableKeyValue::new(Key::new(self), Item::None)) - .value - }), + Item::Value(ref mut v) => v + .as_inline_table_mut() + .map(|t| t.items.entry(Key::new(self)).or_insert_with(|| Item::None)), _ => None, } } diff --git a/crates/toml_edit/src/inline_table.rs b/crates/toml_edit/src/inline_table.rs index c0a58fe6..462294b6 100644 --- a/crates/toml_edit/src/inline_table.rs +++ b/crates/toml_edit/src/inline_table.rs @@ -2,7 +2,7 @@ use std::iter::FromIterator; use crate::key::Key; use crate::repr::Decor; -use crate::table::{Iter, IterMut, KeyValuePairs, TableKeyValue, TableLike}; +use crate::table::{Iter, IterMut, KeyValuePairs, TableLike}; use crate::{InternalString, Item, KeyMut, RawString, Table, Value}; /// Type representing a TOML inline table, @@ -62,10 +62,10 @@ impl InlineTable { parent: &[&'s Key], values: &mut Vec<(Vec<&'s Key>, &'s Value)>, ) { - for value in self.items.values() { + for (key, value) in self.items.iter() { let mut path = parent.to_vec(); - path.push(&value.key); - match &value.value { + path.push(key); + match value { Item::Value(Value::InlineTable(table)) if table.is_dotted() => { table.append_values(&path, values); } @@ -86,8 +86,8 @@ impl InlineTable { pub fn sort_values(&mut self) { // Assuming standard tables have their position set and this won't negatively impact them self.items.sort_keys(); - for kv in self.items.values_mut() { - match &mut kv.value { + for value in self.items.values_mut() { + match value { Item::Value(Value::InlineTable(table)) if table.is_dotted() => { table.sort_values(); } @@ -111,22 +111,19 @@ impl InlineTable { where F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering, { - let modified_cmp = |_: &InternalString, - val1: &TableKeyValue, - _: &InternalString, - val2: &TableKeyValue| - -> std::cmp::Ordering { - match (val1.value.as_value(), val2.value.as_value()) { - (Some(v1), Some(v2)) => compare(&val1.key, v1, &val2.key, v2), - (Some(_), None) => std::cmp::Ordering::Greater, - (None, Some(_)) => std::cmp::Ordering::Less, - (None, None) => std::cmp::Ordering::Equal, - } - }; + let modified_cmp = + |key1: &Key, val1: &Item, key2: &Key, val2: &Item| -> std::cmp::Ordering { + match (val1.as_value(), val2.as_value()) { + (Some(v1), Some(v2)) => compare(key1, v1, key2, v2), + (Some(_), None) => std::cmp::Ordering::Greater, + (None, Some(_)) => std::cmp::Ordering::Less, + (None, None) => std::cmp::Ordering::Equal, + } + }; self.items.sort_by(modified_cmp); - for kv in self.items.values_mut() { - match &mut kv.value { + for value in self.items.values_mut() { + match value { Item::Value(Value::InlineTable(table)) if table.is_dotted() => { table.sort_values_by_internal(compare); } @@ -187,26 +184,32 @@ impl InlineTable { /// Returns an accessor to a key's formatting pub fn key(&self, key: &str) -> Option<&'_ Key> { - self.items.get(key).map(|kv| &kv.key) + self.items.get_full(key).map(|(_, key, _)| key) } /// Returns an accessor to a key's formatting pub fn key_mut(&mut self, key: &str) -> Option> { - self.items.get_mut(key).map(|kv| kv.key.as_mut()) + use indexmap::map::MutableKeys; + self.items + .get_full_mut2(key) + .map(|(_, key, _)| key.as_mut()) } /// Returns the decor associated with a given key of the table. #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { #![allow(deprecated)] - self.items.get_mut(key).map(|kv| kv.key.leaf_decor_mut()) + use indexmap::map::MutableKeys; + self.items + .get_full_mut2(key) + .map(|(_, key, _)| key.leaf_decor_mut()) } /// Returns the decor associated with a given key of the table. #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor(&self, key: &str) -> Option<&Decor> { #![allow(deprecated)] - self.items.get(key).map(|kv| kv.key.leaf_decor()) + self.items.get_full(key).map(|(_, key, _)| key.leaf_decor()) } /// Set whitespace after before element @@ -227,12 +230,13 @@ impl InlineTable { } pub(crate) fn despan(&mut self, input: &str) { + use indexmap::map::MutableKeys; self.span = None; self.decor.despan(input); self.preamble.despan(input); - for kv in self.items.values_mut() { - kv.key.despan(input); - kv.value.despan(input); + for (key, value) in self.items.iter_mut2() { + key.despan(input); + value.despan(input); } } } @@ -243,18 +247,19 @@ impl InlineTable { Box::new( self.items .iter() - .filter(|&(_, kv)| kv.value.is_value()) - .map(|(k, kv)| (&k[..], kv.value.as_value().unwrap())), + .filter(|(_, value)| !value.is_none()) + .map(|(key, value)| (key.get(), value.as_value().unwrap())), ) } /// Returns an iterator over key/value pairs. pub fn iter_mut(&mut self) -> InlineTableIterMut<'_> { + use indexmap::map::MutableKeys; Box::new( self.items - .iter_mut() - .filter(|(_, kv)| kv.value.is_value()) - .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())), + .iter_mut2() + .filter(|(_, value)| value.is_value()) + .map(|(key, value)| (key.as_mut(), value.as_value_mut().unwrap())), ) } @@ -275,10 +280,10 @@ impl InlineTable { /// Gets the given key's corresponding entry in the Table for in-place manipulation. pub fn entry(&'_ mut self, key: impl Into) -> InlineEntry<'_> { - match self.items.entry(key.into()) { + match self.items.entry(key.into().into()) { indexmap::map::Entry::Occupied(mut entry) => { // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. - let scratch = std::mem::take(&mut entry.get_mut().value); + let scratch = std::mem::take(entry.get_mut()); let scratch = Item::Value( scratch .into_value() @@ -286,23 +291,21 @@ impl InlineTable { // "safe" value .unwrap_or_else(|_| Value::InlineTable(Default::default())), ); - entry.get_mut().value = scratch; + *entry.get_mut() = scratch; InlineEntry::Occupied(InlineOccupiedEntry { entry }) } - indexmap::map::Entry::Vacant(entry) => { - InlineEntry::Vacant(InlineVacantEntry { entry, key: None }) - } + indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { entry }), } } /// Gets the given key's corresponding entry in the Table for in-place manipulation. pub fn entry_format<'a>(&'a mut self, key: &Key) -> InlineEntry<'a> { // Accept a `&Key` to be consistent with `entry` - match self.items.entry(key.get().into()) { + match self.items.entry(key.clone()) { indexmap::map::Entry::Occupied(mut entry) => { // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. - let scratch = std::mem::take(&mut entry.get_mut().value); + let scratch = std::mem::take(entry.get_mut()); let scratch = Item::Value( scratch .into_value() @@ -310,33 +313,30 @@ impl InlineTable { // "safe" value .unwrap_or_else(|_| Value::InlineTable(Default::default())), ); - entry.get_mut().value = scratch; + *entry.get_mut() = scratch; InlineEntry::Occupied(InlineOccupiedEntry { entry }) } - indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { - entry, - key: Some(key.clone()), - }), + indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { entry }), } } /// Return an optional reference to the value at the given the key. pub fn get(&self, key: &str) -> Option<&Value> { - self.items.get(key).and_then(|kv| kv.value.as_value()) + self.items.get(key).and_then(|value| value.as_value()) } /// Return an optional mutable reference to the value at the given the key. pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> { self.items .get_mut(key) - .and_then(|kv| kv.value.as_value_mut()) + .and_then(|value| value.as_value_mut()) } /// Return references to the key-value pair stored for key, if it is present, else None. pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { - self.items.get(key).and_then(|kv| { - if !kv.value.is_none() { - Some((&kv.key, &kv.value)) + self.items.get_full(key).and_then(|(_, key, value)| { + if !value.is_none() { + Some((key, value)) } else { None } @@ -345,9 +345,10 @@ impl InlineTable { /// Return mutable references to the key-value pair stored for key, if it is present, else None. pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { - self.items.get_mut(key).and_then(|kv| { - if !kv.value.is_none() { - Some((kv.key.as_mut(), &mut kv.value)) + use indexmap::map::MutableKeys; + self.items.get_full_mut2(key).and_then(|(_, key, value)| { + if !value.is_none() { + Some((key.as_mut(), value)) } else { None } @@ -356,8 +357,8 @@ impl InlineTable { /// Returns true if the table contains given key. pub fn contains_key(&self, key: &str) -> bool { - if let Some(kv) = self.items.get(key) { - kv.value.is_value() + if let Some(value) = self.items.get(key) { + value.is_value() } else { false } @@ -372,44 +373,42 @@ impl InlineTable { ) -> &mut Value { let key = key.into(); self.items - .entry(key.clone()) - .or_insert(TableKeyValue::new(Key::new(key), Item::Value(value.into()))) - .value + .entry(Key::new(key)) + .or_insert(Item::Value(value.into())) .as_value_mut() .expect("non-value type in inline table") } /// Inserts a key-value pair into the map. pub fn insert(&mut self, key: impl Into, value: Value) -> Option { - let key = key.into(); - let kv = TableKeyValue::new(Key::new(key.clone()), Item::Value(value)); + let key = Key::new(key.into()); + let value = Item::Value(value); self.items - .insert(key, kv) - .and_then(|kv| kv.value.into_value().ok()) + .insert(key, value) + .and_then(|old| old.into_value().ok()) } /// Inserts a key-value pair into the map. pub fn insert_formatted(&mut self, key: &Key, value: Value) -> Option { - let kv = TableKeyValue::new(key.to_owned(), Item::Value(value)); + let key = key.to_owned(); + let value = Item::Value(value); self.items - .insert(InternalString::from(key.get()), kv) - .filter(|kv| kv.value.is_value()) - .map(|kv| kv.value.into_value().unwrap()) + .insert(key, value) + .and_then(|old| old.into_value().ok()) } /// Removes an item given the key. pub fn remove(&mut self, key: &str) -> Option { self.items .shift_remove(key) - .and_then(|kv| kv.value.into_value().ok()) + .and_then(|value| value.into_value().ok()) } /// Removes a key from the map, returning the stored key and value if the key was previously in the map. pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Value)> { - self.items.shift_remove(key).and_then(|kv| { - let key = kv.key; - kv.value.into_value().ok().map(|value| (key, value)) - }) + self.items + .shift_remove_entry(key) + .and_then(|(key, value)| Some((key, value.into_value().ok()?))) } /// Retains only the elements specified by the `keep` predicate. @@ -423,8 +422,7 @@ impl InlineTable { F: FnMut(&str, &mut Value) -> bool, { self.items.retain(|key, item| { - item.value - .as_value_mut() + item.as_value_mut() .map(|value| keep(key, value)) .unwrap_or(false) }); @@ -443,9 +441,7 @@ impl, V: Into> Extend<(K, V)> for InlineTable { for (key, value) in iter { let key = key.into(); let value = Item::Value(value.into()); - let value = TableKeyValue::new(key, value); - self.items - .insert(InternalString::from(value.key.get()), value); + self.items.insert(key, value); } } } @@ -469,8 +465,8 @@ impl IntoIterator for InlineTable { Box::new( self.items .into_iter() - .filter(|(_, kv)| kv.value.is_value()) - .map(|(k, kv)| (k, kv.value.into_value().unwrap())), + .filter(|(_, value)| value.is_value()) + .map(|(key, value)| (key.into(), value.into_value().unwrap())), ) } } @@ -485,11 +481,12 @@ impl<'s> IntoIterator for &'s InlineTable { } fn decorate_inline_table(table: &mut InlineTable) { + use indexmap::map::MutableKeys; for (mut key, value) in table .items - .iter_mut() - .filter(|(_, kv)| kv.value.is_value()) - .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())) + .iter_mut2() + .filter(|(_, value)| value.is_value()) + .map(|(key, value)| (key.as_mut(), value.as_value_mut().unwrap())) { key.leaf_decor_mut().clear(); key.dotted_decor_mut().clear(); @@ -506,13 +503,14 @@ pub type InlineTableIterMut<'a> = Box, &'a mut V impl TableLike for InlineTable { fn iter(&self) -> Iter<'_> { - Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value))) + Box::new(self.items.iter().map(|(key, value)| (key.get(), value))) } fn iter_mut(&mut self) -> IterMut<'_> { + use indexmap::map::MutableKeys; Box::new( self.items - .iter_mut() - .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)), + .iter_mut2() + .map(|(key, value)| (key.as_mut(), value)), ) } fn clear(&mut self) { @@ -525,7 +523,7 @@ impl TableLike for InlineTable { crate::Entry::Occupied(crate::OccupiedEntry { entry }) } indexmap::map::Entry::Vacant(entry) => { - crate::Entry::Vacant(crate::VacantEntry { entry, key: None }) + crate::Entry::Vacant(crate::VacantEntry { entry }) } } } @@ -535,17 +533,16 @@ impl TableLike for InlineTable { indexmap::map::Entry::Occupied(entry) => { crate::Entry::Occupied(crate::OccupiedEntry { entry }) } - indexmap::map::Entry::Vacant(entry) => crate::Entry::Vacant(crate::VacantEntry { - entry, - key: Some(key.to_owned()), - }), + indexmap::map::Entry::Vacant(entry) => { + crate::Entry::Vacant(crate::VacantEntry { entry }) + } } } fn get<'s>(&'s self, key: &str) -> Option<&'s Item> { - self.items.get(key).map(|kv| &kv.value) + self.items.get(key) } fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> { - self.items.get_mut(key).map(|kv| &mut kv.value) + self.items.get_mut(key) } fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { self.get_key_value(key) @@ -647,7 +644,7 @@ impl<'a> InlineEntry<'a> { /// A view into a single occupied location in a `IndexMap`. pub struct InlineOccupiedEntry<'a> { - entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>, + entry: indexmap::map::OccupiedEntry<'a, Key, Item>, } impl<'a> InlineOccupiedEntry<'a> { @@ -663,47 +660,46 @@ impl<'a> InlineOccupiedEntry<'a> { /// assert_eq!("foo", map.entry("foo").key()); /// ``` pub fn key(&self) -> &str { - self.entry.key().as_str() + self.entry.key().get() } /// Gets a mutable reference to the entry key pub fn key_mut(&mut self) -> KeyMut<'_> { - self.entry.get_mut().key.as_mut() + use indexmap::map::MutableEntryKey; + self.entry.key_mut().as_mut() } /// Gets a reference to the value in the entry. pub fn get(&self) -> &Value { - self.entry.get().value.as_value().unwrap() + self.entry.get().as_value().unwrap() } /// Gets a mutable reference to the value in the entry. pub fn get_mut(&mut self) -> &mut Value { - self.entry.get_mut().value.as_value_mut().unwrap() + self.entry.get_mut().as_value_mut().unwrap() } /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the map itself pub fn into_mut(self) -> &'a mut Value { - self.entry.into_mut().value.as_value_mut().unwrap() + self.entry.into_mut().as_value_mut().unwrap() } /// Sets the value of the entry, and returns the entry's old value pub fn insert(&mut self, value: Value) -> Value { - let mut value = Item::Value(value); - std::mem::swap(&mut value, &mut self.entry.get_mut().value); - value.into_value().unwrap() + let value = Item::Value(value); + self.entry.insert(value).into_value().unwrap() } /// Takes the value out of the entry, and returns it pub fn remove(self) -> Value { - self.entry.shift_remove().value.into_value().unwrap() + self.entry.shift_remove().into_value().unwrap() } } /// A view into a single empty location in a `IndexMap`. pub struct InlineVacantEntry<'a> { - entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>, - key: Option, + entry: indexmap::map::VacantEntry<'a, Key, Item>, } impl<'a> InlineVacantEntry<'a> { @@ -719,19 +715,14 @@ impl<'a> InlineVacantEntry<'a> { /// assert_eq!("foo", map.entry("foo").key()); /// ``` pub fn key(&self) -> &str { - self.entry.key().as_str() + self.entry.key().get() } /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it pub fn insert(self, value: Value) -> &'a mut Value { let entry = self.entry; - let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str())); let value = Item::Value(value); - entry - .insert(TableKeyValue::new(key, value)) - .value - .as_value_mut() - .unwrap() + entry.insert(value).as_value_mut().unwrap() } } diff --git a/crates/toml_edit/src/key.rs b/crates/toml_edit/src/key.rs index 15fdd4de..314870f5 100644 --- a/crates/toml_edit/src/key.rs +++ b/crates/toml_edit/src/key.rs @@ -86,10 +86,6 @@ impl Key { &self.key } - pub(crate) fn get_internal(&self) -> &InternalString { - &self.key - } - /// Returns key raw representation, if available. pub fn as_repr(&self) -> Option<&Repr> { self.repr.as_ref() @@ -206,6 +202,13 @@ impl std::ops::Deref for Key { } } +impl std::borrow::Borrow for Key { + #[inline] + fn borrow(&self) -> &str { + self.get() + } +} + impl std::hash::Hash for Key { fn hash(&self, state: &mut H) { self.get().hash(state); diff --git a/crates/toml_edit/src/parser/document.rs b/crates/toml_edit/src/parser/document.rs index bff40bf6..398ee098 100644 --- a/crates/toml_edit/src/parser/document.rs +++ b/crates/toml_edit/src/parser/document.rs @@ -17,7 +17,6 @@ use crate::parser::state::ParseState; use crate::parser::table::table; use crate::parser::trivia::{comment, line_ending, line_trailing, newline, ws}; use crate::parser::value::value; -use crate::table::TableKeyValue; use crate::Item; use crate::RawString; @@ -98,7 +97,7 @@ pub(crate) fn keyval<'s, 'i>( } // keyval = key keyval-sep val -pub(crate) fn parse_keyval(input: &mut Input<'_>) -> PResult<(Vec, TableKeyValue)> { +pub(crate) fn parse_keyval(input: &mut Input<'_>) -> PResult<(Vec, (Key, Item))> { trace( "keyval", ( @@ -124,13 +123,7 @@ pub(crate) fn parse_keyval(input: &mut Input<'_>) -> PResult<(Vec, TableKey let pre = RawString::with_span(pre); let suf = RawString::with_span(suf); let v = v.decorated(pre, suf); - Ok(( - path, - TableKeyValue { - key, - value: Item::Value(v), - }, - )) + Ok((path, (key, Item::Value(v)))) }), ) .parse_next(input) diff --git a/crates/toml_edit/src/parser/inline_table.rs b/crates/toml_edit/src/parser/inline_table.rs index bba5100d..6eb06a31 100644 --- a/crates/toml_edit/src/parser/inline_table.rs +++ b/crates/toml_edit/src/parser/inline_table.rs @@ -10,8 +10,7 @@ use crate::parser::key::key; use crate::parser::prelude::*; use crate::parser::trivia::ws; use crate::parser::value::value; -use crate::table::TableKeyValue; -use crate::{InlineTable, InternalString, Item, RawString, Value}; +use crate::{InlineTable, Item, RawString, Value}; use indexmap::map::Entry; @@ -33,7 +32,7 @@ pub(crate) fn inline_table<'i>(input: &mut Input<'i>) -> PResult { } fn table_from_pairs( - v: Vec<(Vec, TableKeyValue)>, + v: Vec<(Vec, (Key, Item))>, preamble: RawString, ) -> Result { let mut root = InlineTable::new(); @@ -41,26 +40,25 @@ fn table_from_pairs( // Assuming almost all pairs will be directly in `root` root.items.reserve(v.len()); - for (path, kv) in v { + for (path, (key, value)) in v { let table = descend_path(&mut root, &path)?; // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed" let mixed_table_types = table.is_dotted() == path.is_empty(); if mixed_table_types { return Err(CustomError::DuplicateKey { - key: kv.key.get().into(), + key: key.get().into(), table: None, }); } - let key: InternalString = kv.key.get_internal().into(); match table.items.entry(key) { Entry::Vacant(o) => { - o.insert(kv); + o.insert(value); } Entry::Occupied(o) => { return Err(CustomError::DuplicateKey { - key: o.key().as_str().into(), + key: o.key().get().into(), table: None, }); } @@ -119,7 +117,7 @@ pub(crate) const KEYVAL_SEP: u8 = b'='; fn inline_table_keyvals( input: &mut Input<'_>, -) -> PResult<(Vec<(Vec, TableKeyValue)>, RawString)> { +) -> PResult<(Vec<(Vec, (Key, Item))>, RawString)> { ( separated(0.., keyval, INLINE_TABLE_SEP), ws.span().map(RawString::with_span), @@ -127,7 +125,7 @@ fn inline_table_keyvals( .parse_next(input) } -fn keyval(input: &mut Input<'_>) -> PResult<(Vec, TableKeyValue)> { +fn keyval(input: &mut Input<'_>) -> PResult<(Vec, (Key, Item))> { ( key, cut_err(( @@ -145,13 +143,7 @@ fn keyval(input: &mut Input<'_>) -> PResult<(Vec, TableKeyValue)> { let pre = RawString::with_span(pre); let suf = RawString::with_span(suf); let v = v.decorated(pre, suf); - ( - path, - TableKeyValue { - key, - value: Item::Value(v), - }, - ) + (path, (key, Item::Value(v))) }) .parse_next(input) } diff --git a/crates/toml_edit/src/parser/state.rs b/crates/toml_edit/src/parser/state.rs index 2513634a..6a234136 100644 --- a/crates/toml_edit/src/parser/state.rs +++ b/crates/toml_edit/src/parser/state.rs @@ -1,8 +1,7 @@ use crate::key::Key; use crate::parser::error::CustomError; use crate::repr::Decor; -use crate::table::TableKeyValue; -use crate::{ArrayOfTables, ImDocument, InternalString, Item, RawString, Table}; +use crate::{ArrayOfTables, ImDocument, Item, RawString, Table}; pub(crate) struct ParseState { root: Table, @@ -56,24 +55,23 @@ impl ParseState { pub(crate) fn on_keyval( &mut self, path: Vec, - mut kv: TableKeyValue, + (mut key, value): (Key, Item), ) -> Result<(), CustomError> { { let mut prefix = self.trailing.take(); let prefix = match ( prefix.take(), - kv.key.leaf_decor.prefix().and_then(|d| d.span()), + key.leaf_decor.prefix().and_then(|d| d.span()), ) { (Some(p), Some(k)) => Some(p.start..k.end), (Some(p), None) | (None, Some(p)) => Some(p), (None, None) => None, }; - kv.key - .leaf_decor + key.leaf_decor .set_prefix(prefix.map(RawString::with_span).unwrap_or_default()); } - if let (Some(existing), Some(value)) = (self.current_table.span(), kv.value.span()) { + if let (Some(existing), Some(value)) = (self.current_table.span(), value.span()) { self.current_table.span = Some((existing.start)..(value.end)); } let table = &mut self.current_table; @@ -83,20 +81,19 @@ impl ParseState { let mixed_table_types = table.is_dotted() == path.is_empty(); if mixed_table_types { return Err(CustomError::DuplicateKey { - key: kv.key.get().into(), + key: key.get().into(), table: None, }); } - let key: InternalString = kv.key.get_internal().into(); match table.items.entry(key) { indexmap::map::Entry::Vacant(o) => { - o.insert(kv); + o.insert(value); } indexmap::map::Entry::Occupied(o) => { // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed" return Err(CustomError::DuplicateKey { - key: o.key().as_str().into(), + key: o.key().get().into(), table: Some(self.current_table_path.clone()), }); } diff --git a/crates/toml_edit/src/ser/key.rs b/crates/toml_edit/src/ser/key.rs index 3ba08406..6ebbc7ac 100644 --- a/crates/toml_edit/src/ser/key.rs +++ b/crates/toml_edit/src/ser/key.rs @@ -1,92 +1,92 @@ -use crate::InternalString; +use crate::Key; use super::Error; pub(crate) struct KeySerializer; impl serde::ser::Serializer for KeySerializer { - type Ok = InternalString; + type Ok = Key; type Error = Error; - type SerializeSeq = serde::ser::Impossible; - type SerializeTuple = serde::ser::Impossible; - type SerializeTupleStruct = serde::ser::Impossible; - type SerializeTupleVariant = serde::ser::Impossible; - type SerializeMap = serde::ser::Impossible; - type SerializeStruct = serde::ser::Impossible; - type SerializeStructVariant = serde::ser::Impossible; + type SerializeSeq = serde::ser::Impossible; + type SerializeTuple = serde::ser::Impossible; + type SerializeTupleStruct = serde::ser::Impossible; + type SerializeTupleVariant = serde::ser::Impossible; + type SerializeMap = serde::ser::Impossible; + type SerializeStruct = serde::ser::Impossible; + type SerializeStructVariant = serde::ser::Impossible; - fn serialize_bool(self, _v: bool) -> Result { + fn serialize_bool(self, _v: bool) -> Result { Err(Error::KeyNotString) } - fn serialize_i8(self, _v: i8) -> Result { + fn serialize_i8(self, _v: i8) -> Result { Err(Error::KeyNotString) } - fn serialize_i16(self, _v: i16) -> Result { + fn serialize_i16(self, _v: i16) -> Result { Err(Error::KeyNotString) } - fn serialize_i32(self, _v: i32) -> Result { + fn serialize_i32(self, _v: i32) -> Result { Err(Error::KeyNotString) } - fn serialize_i64(self, _v: i64) -> Result { + fn serialize_i64(self, _v: i64) -> Result { Err(Error::KeyNotString) } - fn serialize_u8(self, _v: u8) -> Result { + fn serialize_u8(self, _v: u8) -> Result { Err(Error::KeyNotString) } - fn serialize_u16(self, _v: u16) -> Result { + fn serialize_u16(self, _v: u16) -> Result { Err(Error::KeyNotString) } - fn serialize_u32(self, _v: u32) -> Result { + fn serialize_u32(self, _v: u32) -> Result { Err(Error::KeyNotString) } - fn serialize_u64(self, _v: u64) -> Result { + fn serialize_u64(self, _v: u64) -> Result { Err(Error::KeyNotString) } - fn serialize_f32(self, _v: f32) -> Result { + fn serialize_f32(self, _v: f32) -> Result { Err(Error::KeyNotString) } - fn serialize_f64(self, _v: f64) -> Result { + fn serialize_f64(self, _v: f64) -> Result { Err(Error::KeyNotString) } - fn serialize_char(self, _v: char) -> Result { + fn serialize_char(self, _v: char) -> Result { Err(Error::KeyNotString) } - fn serialize_str(self, value: &str) -> Result { - Ok(InternalString::from(value)) + fn serialize_str(self, value: &str) -> Result { + Ok(Key::new(value)) } - fn serialize_bytes(self, _value: &[u8]) -> Result { + fn serialize_bytes(self, _value: &[u8]) -> Result { Err(Error::KeyNotString) } - fn serialize_none(self) -> Result { + fn serialize_none(self) -> Result { Err(Error::KeyNotString) } - fn serialize_some(self, _value: &T) -> Result + fn serialize_some(self, _value: &T) -> Result where T: serde::ser::Serialize + ?Sized, { Err(Error::KeyNotString) } - fn serialize_unit(self) -> Result { + fn serialize_unit(self) -> Result { Err(Error::KeyNotString) } - fn serialize_unit_struct(self, _name: &'static str) -> Result { + fn serialize_unit_struct(self, _name: &'static str) -> Result { Err(Error::KeyNotString) } @@ -95,15 +95,11 @@ impl serde::ser::Serializer for KeySerializer { _name: &'static str, _variant_index: u32, variant: &'static str, - ) -> Result { + ) -> Result { Ok(variant.into()) } - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result where T: serde::ser::Serialize + ?Sized, { @@ -116,7 +112,7 @@ impl serde::ser::Serializer for KeySerializer { _variant_index: u32, _variant: &'static str, _value: &T, - ) -> Result + ) -> Result where T: serde::ser::Serialize + ?Sized, { diff --git a/crates/toml_edit/src/ser/map.rs b/crates/toml_edit/src/ser/map.rs index 49029028..f1924982 100644 --- a/crates/toml_edit/src/ser/map.rs +++ b/crates/toml_edit/src/ser/map.rs @@ -131,7 +131,7 @@ impl serde::ser::SerializeStruct for SerializeDatetime { #[doc(hidden)] pub struct SerializeInlineTable { items: crate::table::KeyValuePairs, - key: Option, + key: Option, } impl SerializeInlineTable { @@ -170,11 +170,8 @@ impl serde::ser::SerializeMap for SerializeInlineTable { match res { Ok(item) => { let key = self.key.take().unwrap(); - let kv = crate::table::TableKeyValue::new( - crate::Key::new(&key), - crate::Item::Value(item), - ); - self.items.insert(key, kv); + let item = crate::Item::Value(item); + self.items.insert(key, item); } Err(e) => { if !(e == Error::UnsupportedNone && value_serializer.is_none) { @@ -202,11 +199,8 @@ impl serde::ser::SerializeStruct for SerializeInlineTable { let res = value.serialize(&mut value_serializer); match res { Ok(item) => { - let kv = crate::table::TableKeyValue::new( - crate::Key::new(key), - crate::Item::Value(item), - ); - self.items.insert(crate::InternalString::from(key), kv); + let item = crate::Item::Value(item); + self.items.insert(crate::Key::new(key), item); } Err(e) => { if !(e == Error::UnsupportedNone && value_serializer.is_none) { @@ -613,11 +607,8 @@ impl serde::ser::SerializeTupleVariant for SerializeVariant fn end(self) -> Result { let inner = serde::ser::SerializeSeq::end(self.inner)?; let mut items = crate::table::KeyValuePairs::new(); - let kv = crate::table::TableKeyValue::new( - crate::Key::new(self.variant), - crate::Item::Value(inner), - ); - items.insert(crate::InternalString::from(self.variant), kv); + let value = crate::Item::Value(inner); + items.insert(crate::Key::new(self.variant), value); Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs( items, ))) @@ -640,11 +631,8 @@ impl serde::ser::SerializeStructVariant for SerializeVariant { fn end(self) -> Result { let inner = serde::ser::SerializeStruct::end(self.inner)?; let mut items = crate::table::KeyValuePairs::new(); - let kv = crate::table::TableKeyValue::new( - crate::Key::new(self.variant), - crate::Item::Value(inner), - ); - items.insert(crate::InternalString::from(self.variant), kv); + let value = crate::Item::Value(inner); + items.insert(crate::Key::new(self.variant), value); Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs( items, ))) diff --git a/crates/toml_edit/src/table.rs b/crates/toml_edit/src/table.rs index 2863946f..0238b2b7 100644 --- a/crates/toml_edit/src/table.rs +++ b/crates/toml_edit/src/table.rs @@ -49,8 +49,8 @@ impl Table { /// Convert to an inline table pub fn into_inline_table(mut self) -> InlineTable { - for (_, kv) in self.items.iter_mut() { - kv.value.make_value(); + for (_, value) in self.items.iter_mut() { + value.make_value(); } let mut t = InlineTable::with_pairs(self.items); t.fmt(); @@ -75,10 +75,10 @@ impl Table { parent: &[&'s Key], values: &mut Vec<(Vec<&'s Key>, &'s Value)>, ) { - for value in self.items.values() { + for (key, value) in self.items.iter() { let mut path = parent.to_vec(); - path.push(&value.key); - match &value.value { + path.push(key); + match value { Item::Table(table) if table.is_dotted() => { table.append_values(&path, values); } @@ -109,8 +109,8 @@ impl Table { pub fn sort_values(&mut self) { // Assuming standard tables have their doc_position set and this won't negatively impact them self.items.sort_keys(); - for kv in self.items.values_mut() { - match &mut kv.value { + for value in self.items.values_mut() { + match value { Item::Table(table) if table.is_dotted() => { table.sort_values(); } @@ -134,18 +134,15 @@ impl Table { where F: FnMut(&Key, &Item, &Key, &Item) -> std::cmp::Ordering, { - let modified_cmp = |_: &InternalString, - val1: &TableKeyValue, - _: &InternalString, - val2: &TableKeyValue| - -> std::cmp::Ordering { - compare(&val1.key, &val1.value, &val2.key, &val2.value) - }; + let modified_cmp = + |key1: &Key, val1: &Item, key2: &Key, val2: &Item| -> std::cmp::Ordering { + compare(key1, val1, key2, val2) + }; self.items.sort_by(modified_cmp); - for kv in self.items.values_mut() { - match &mut kv.value { + for value in self.items.values_mut() { + match value { Item::Table(table) if table.is_dotted() => { table.sort_values_by_internal(compare); } @@ -220,26 +217,32 @@ impl Table { /// Returns an accessor to a key's formatting pub fn key(&self, key: &str) -> Option<&'_ Key> { - self.items.get(key).map(|kv| &kv.key) + self.items.get_full(key).map(|(_, key, _)| key) } /// Returns an accessor to a key's formatting pub fn key_mut(&mut self, key: &str) -> Option> { - self.items.get_mut(key).map(|kv| kv.key.as_mut()) + use indexmap::map::MutableKeys; + self.items + .get_full_mut2(key) + .map(|(_, key, _)| key.as_mut()) } /// Returns the decor associated with a given key of the table. #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { #![allow(deprecated)] - self.items.get_mut(key).map(|kv| kv.key.leaf_decor_mut()) + use indexmap::map::MutableKeys; + self.items + .get_full_mut2(key) + .map(|(_, key, _)| key.leaf_decor_mut()) } /// Returns the decor associated with a given key of the table. #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor(&self, key: &str) -> Option<&Decor> { #![allow(deprecated)] - self.items.get(key).map(|kv| kv.key.leaf_decor()) + self.items.get_full(key).map(|(_, key, _)| key.leaf_decor()) } /// The location within the original document @@ -250,11 +253,12 @@ impl Table { } pub(crate) fn despan(&mut self, input: &str) { + use indexmap::map::MutableKeys; self.span = None; self.decor.despan(input); - for kv in self.items.values_mut() { - kv.key.despan(input); - kv.value.despan(input); + for (key, value) in self.items.iter_mut2() { + key.despan(input); + value.despan(input); } } } @@ -265,24 +269,25 @@ impl Table { Box::new( self.items .iter() - .filter(|(_, kv)| !kv.value.is_none()) - .map(|(key, kv)| (&key[..], &kv.value)), + .filter(|(_, value)| !value.is_none()) + .map(|(key, value)| (key.get(), value)), ) } /// Returns an mutable iterator over all key/value pairs, including empty. pub fn iter_mut(&mut self) -> IterMut<'_> { + use indexmap::map::MutableKeys; Box::new( self.items - .iter_mut() - .filter(|(_, kv)| !kv.value.is_none()) - .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)), + .iter_mut2() + .filter(|(_, value)| !value.is_none()) + .map(|(key, value)| (key.as_mut(), value)), ) } /// Returns the number of non-empty items in the table. pub fn len(&self) -> usize { - self.items.iter().filter(|i| !(i.1).value.is_none()).count() + self.iter().count() } /// Returns true if the table is empty. @@ -300,49 +305,38 @@ impl Table { // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal match self.items.entry(key.into()) { indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }), - indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, key: None }), + indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry }), } } /// Gets the given key's corresponding entry in the Table for in-place manipulation. pub fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a> { // Accept a `&Key` to be consistent with `entry` - match self.items.entry(key.get().into()) { + match self.items.entry(key.clone()) { indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }), - indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { - entry, - key: Some(key.to_owned()), - }), + indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry }), } } /// Returns an optional reference to an item given the key. pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> { - self.items.get(key).and_then(|kv| { - if !kv.value.is_none() { - Some(&kv.value) - } else { - None - } - }) + self.items + .get(key) + .and_then(|value| if !value.is_none() { Some(value) } else { None }) } /// Returns an optional mutable reference to an item given the key. pub fn get_mut<'a>(&'a mut self, key: &str) -> Option<&'a mut Item> { - self.items.get_mut(key).and_then(|kv| { - if !kv.value.is_none() { - Some(&mut kv.value) - } else { - None - } - }) + self.items + .get_mut(key) + .and_then(|value| if !value.is_none() { Some(value) } else { None }) } /// Return references to the key-value pair stored for key, if it is present, else None. pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { - self.items.get(key).and_then(|kv| { - if !kv.value.is_none() { - Some((&kv.key, &kv.value)) + self.items.get_full(key).and_then(|(_, key, value)| { + if !value.is_none() { + Some((key, value)) } else { None } @@ -351,9 +345,10 @@ impl Table { /// Return mutable references to the key-value pair stored for key, if it is present, else None. pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { - self.items.get_mut(key).and_then(|kv| { - if !kv.value.is_none() { - Some((kv.key.as_mut(), &mut kv.value)) + use indexmap::map::MutableKeys; + self.items.get_full_mut2(key).and_then(|(_, key, value)| { + if !value.is_none() { + Some((key.as_mut(), value)) } else { None } @@ -362,8 +357,8 @@ impl Table { /// Returns true if the table contains an item with the given key. pub fn contains_key(&self, key: &str) -> bool { - if let Some(kv) = self.items.get(key) { - !kv.value.is_none() + if let Some(value) = self.items.get(key) { + !value.is_none() } else { false } @@ -371,8 +366,8 @@ impl Table { /// Returns true if the table contains a table with the given key. pub fn contains_table(&self, key: &str) -> bool { - if let Some(kv) = self.items.get(key) { - kv.value.is_table() + if let Some(value) = self.items.get(key) { + value.is_table() } else { false } @@ -380,8 +375,8 @@ impl Table { /// Returns true if the table contains a value with the given key. pub fn contains_value(&self, key: &str) -> bool { - if let Some(kv) = self.items.get(key) { - kv.value.is_value() + if let Some(value) = self.items.get(key) { + value.is_value() } else { false } @@ -389,8 +384,8 @@ impl Table { /// Returns true if the table contains an array of tables with the given key. pub fn contains_array_of_tables(&self, key: &str) -> bool { - if let Some(kv) = self.items.get(key) { - kv.value.is_array_of_tables() + if let Some(value) = self.items.get(key) { + value.is_array_of_tables() } else { false } @@ -398,24 +393,24 @@ impl Table { /// Inserts a key-value pair into the map. pub fn insert(&mut self, key: &str, item: Item) -> Option { - let kv = TableKeyValue::new(Key::new(key), item); - self.items.insert(key.into(), kv).map(|kv| kv.value) + let key = Key::new(key); + self.items.insert(key, item) } /// Inserts a key-value pair into the map. pub fn insert_formatted(&mut self, key: &Key, item: Item) -> Option { - let kv = TableKeyValue::new(key.to_owned(), item); - self.items.insert(key.get().into(), kv).map(|kv| kv.value) + let key = key.to_owned(); + self.items.insert(key, item) } /// Removes an item given the key. pub fn remove(&mut self, key: &str) -> Option { - self.items.shift_remove(key).map(|kv| kv.value) + self.items.shift_remove(key) } /// Removes a key from the map, returning the stored key and value if the key was previously in the map. pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Item)> { - self.items.shift_remove(key).map(|kv| (kv.key, kv.value)) + self.items.shift_remove_entry(key) } /// Retains only the elements specified by the `keep` predicate. @@ -428,8 +423,7 @@ impl Table { where F: FnMut(&str, &mut Item) -> bool, { - self.items - .retain(|key, key_value| keep(key, &mut key_value.value)); + self.items.retain(|key, value| keep(key, value)); } } @@ -453,8 +447,7 @@ impl, V: Into> Extend<(K, V)> for Table { 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().into(), value); + self.items.insert(key, value); } } } @@ -475,7 +468,7 @@ impl IntoIterator for Table { type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { - Box::new(self.items.into_iter().map(|(k, kv)| (k, kv.value))) + Box::new(self.items.into_iter().map(|(k, value)| (k.into(), value))) } } @@ -488,14 +481,15 @@ impl<'s> IntoIterator for &'s Table { } } -pub(crate) type KeyValuePairs = IndexMap; +pub(crate) type KeyValuePairs = IndexMap; fn decorate_table(table: &mut Table) { + use indexmap::map::MutableKeys; for (mut key, value) in table .items - .iter_mut() - .filter(|(_, kv)| kv.value.is_value()) - .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())) + .iter_mut2() + .filter(|(_, value)| value.is_value()) + .map(|(key, value)| (key.as_mut(), value.as_value_mut().unwrap())) { key.leaf_decor_mut().clear(); key.dotted_decor_mut().clear(); @@ -509,18 +503,6 @@ 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 } - } -} - /// An owned iterator type over `Table`'s key/value pairs. pub type IntoIter = Box>; /// An iterator type over `Table`'s key/value pairs. @@ -709,7 +691,7 @@ impl<'a> Entry<'a> { /// A view into a single occupied location in a `IndexMap`. pub struct OccupiedEntry<'a> { - pub(crate) entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>, + pub(crate) entry: indexmap::map::OccupiedEntry<'a, Key, Item>, } impl<'a> OccupiedEntry<'a> { @@ -725,46 +707,45 @@ impl<'a> OccupiedEntry<'a> { /// assert_eq!("foo", map.entry("foo").key()); /// ``` pub fn key(&self) -> &str { - self.entry.key().as_str() + self.entry.key().get() } /// Gets a mutable reference to the entry key pub fn key_mut(&mut self) -> KeyMut<'_> { - self.entry.get_mut().key.as_mut() + use indexmap::map::MutableEntryKey; + self.entry.key_mut().as_mut() } /// Gets a reference to the value in the entry. pub fn get(&self) -> &Item { - &self.entry.get().value + self.entry.get() } /// Gets a mutable reference to the value in the entry. pub fn get_mut(&mut self) -> &mut Item { - &mut self.entry.get_mut().value + self.entry.get_mut() } /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the map itself pub fn into_mut(self) -> &'a mut Item { - &mut self.entry.into_mut().value + self.entry.into_mut() } /// Sets the value of the entry, and returns the entry's old value - pub fn insert(&mut self, mut value: Item) -> Item { - std::mem::swap(&mut value, &mut self.entry.get_mut().value); - value + pub fn insert(&mut self, value: Item) -> Item { + self.entry.insert(value) } /// Takes the value out of the entry, and returns it pub fn remove(self) -> Item { - self.entry.shift_remove().value + self.entry.shift_remove() } } /// A view into a single empty location in a `IndexMap`. pub struct VacantEntry<'a> { - pub(crate) entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>, - pub(crate) key: Option, + pub(crate) entry: indexmap::map::VacantEntry<'a, Key, Item>, } impl<'a> VacantEntry<'a> { @@ -780,14 +761,13 @@ impl<'a> VacantEntry<'a> { /// assert_eq!("foo", map.entry("foo").key()); /// ``` pub fn key(&self) -> &str { - self.entry.key().as_str() + self.entry.key().get() } /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it pub fn insert(self, value: Item) -> &'a mut Item { let entry = self.entry; - let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str())); - &mut entry.insert(TableKeyValue::new(key, value)).value + entry.insert(value) } }