Skip to content

Commit

Permalink
perf(parse): Remove extra key allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jul 31, 2024
1 parent afd3f1f commit 189697d
Show file tree
Hide file tree
Showing 16 changed files with 295 additions and 380 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/toml_edit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
6 changes: 3 additions & 3 deletions crates/toml_edit/src/de/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use super::Error;

pub(crate) struct KeyDeserializer {
span: Option<std::ops::Range<usize>>,
key: crate::InternalString,
key: crate::Key,
}

impl KeyDeserializer {
pub(crate) fn new(key: crate::InternalString, span: Option<std::ops::Range<usize>>) -> Self {
pub(crate) fn new(key: crate::Key, span: Option<std::ops::Range<usize>>) -> Self {
KeyDeserializer { span, key }
}
}
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions crates/toml_edit/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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::<Vec<_>>()
.join(", "),
fields.join(", "),
),
extra_fields[0].key.span(),
extra_fields[0].span(),
))
}
}
13 changes: 7 additions & 6 deletions crates/toml_edit/src/de/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl crate::InlineTable {
}

pub(crate) struct TableMapAccess {
iter: indexmap::map::IntoIter<crate::InternalString, crate::table::TableKeyValue>,
iter: indexmap::map::IntoIter<crate::Key, crate::Item>,
span: Option<std::ops::Range<usize>>,
value: Option<(crate::Key, crate::Item)>,
}
Expand All @@ -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),
Expand Down Expand Up @@ -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))
}
Expand Down
40 changes: 14 additions & 26 deletions crates/toml_edit/src/de/table_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,13 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer {
.items
.into_iter()
.enumerate()
.map(
|(index, (_, value))| match value.key.get().parse::<usize>() {
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::<usize>() {
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?;

Expand All @@ -135,19 +129,13 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer {
.items
.into_iter()
.enumerate()
.map(
|(index, (_, value))| match value.key.get().parse::<usize>() {
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::<usize>() {
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?;

Expand Down
8 changes: 4 additions & 4 deletions crates/toml_edit/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
26 changes: 6 additions & 20 deletions crates/toml_edit/src/index.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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,
}
}
Expand Down
Loading

0 comments on commit 189697d

Please sign in to comment.