diff --git a/crates/toml_edit/src/key.rs b/crates/toml_edit/src/key.rs index 314870f5..e6163763 100644 --- a/crates/toml_edit/src/key.rs +++ b/crates/toml_edit/src/key.rs @@ -32,6 +32,7 @@ pub struct Key { pub(crate) repr: Option, pub(crate) leaf_decor: Decor, pub(crate) dotted_decor: Decor, + pub(crate) position: Option, } impl Key { @@ -42,6 +43,7 @@ impl Key { repr: None, leaf_decor: Default::default(), dotted_decor: Default::default(), + position: Default::default(), } } @@ -76,6 +78,12 @@ impl Key { self } + /// While creating the `Key`, add a table position to it + pub fn with_position(mut self, position: Option) -> Self { + self.position = position; + self + } + /// Access a mutable proxy for the `Key`. pub fn as_mut(&mut self) -> KeyMut<'_> { KeyMut { key: self } @@ -158,6 +166,16 @@ impl Key { } } + /// Get the position relative to other keys in parent table + pub fn position(&self) -> Option { + return self.position; + } + + /// Set the position relative to other keys in parent table + pub fn set_position(&mut self, position: Option) { + self.position = position; + } + /// Auto formats the key. pub fn fmt(&mut self) { self.repr = None; @@ -190,6 +208,7 @@ impl Clone for Key { repr: self.repr.clone(), leaf_decor: self.leaf_decor.clone(), dotted_decor: self.dotted_decor.clone(), + position: self.position.clone(), } } } diff --git a/crates/toml_edit/src/parser/inline_table.rs b/crates/toml_edit/src/parser/inline_table.rs index 6eb06a31..21e1cc20 100644 --- a/crates/toml_edit/src/parser/inline_table.rs +++ b/crates/toml_edit/src/parser/inline_table.rs @@ -40,7 +40,8 @@ fn table_from_pairs( // Assuming almost all pairs will be directly in `root` root.items.reserve(v.len()); - for (path, (key, value)) in v { + for (position, (path, (mut key, value))) in v.into_iter().enumerate() { + key.set_position(Some(position)); let table = descend_path(&mut root, &path)?; // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed" @@ -162,6 +163,7 @@ mod test { r#"{a = 1e165}"#, r#"{ hello = "world", a = 1}"#, r#"{ hello.world = "a" }"#, + r#"{ hello.world = "a", goodbye = "b", hello.moon = "c" }"#, ]; for input in inputs { dbg!(input); diff --git a/crates/toml_edit/src/parser/mod.rs b/crates/toml_edit/src/parser/mod.rs index e0d9e4f0..e8c11abb 100644 --- a/crates/toml_edit/src/parser/mod.rs +++ b/crates/toml_edit/src/parser/mod.rs @@ -216,6 +216,10 @@ that key = "value" "#, r#"hello.world = "a" +"#, + r#"hello.world = "a" +goodbye = "b" +hello.moon = "c" "#, r#"foo = 1979-05-27 # Comment "#, diff --git a/crates/toml_edit/src/parser/state.rs b/crates/toml_edit/src/parser/state.rs index 6a234136..de126df9 100644 --- a/crates/toml_edit/src/parser/state.rs +++ b/crates/toml_edit/src/parser/state.rs @@ -7,6 +7,8 @@ pub(crate) struct ParseState { root: Table, trailing: Option>, current_table_position: usize, + // Current position within a table, to help order dotted keys + current_value_position: usize, current_table: Table, current_is_array: bool, current_table_path: Vec, @@ -20,6 +22,7 @@ impl ParseState { root: Table::new(), trailing: None, current_table_position: 0, + current_value_position: 0, current_table: root, current_is_array: false, current_table_path: Vec::new(), @@ -74,6 +77,9 @@ impl ParseState { if let (Some(existing), Some(value)) = (self.current_table.span(), value.span()) { self.current_table.span = Some((existing.start)..(value.end)); } + key.set_position(Some(self.current_value_position)); + self.current_value_position += 1; + let table = &mut self.current_table; let table = Self::descend_path(table, &path, true)?; @@ -161,6 +167,7 @@ impl ParseState { } self.current_table_position += 1; + self.current_value_position = 0; self.current_table.decor = decor; self.current_table.set_implicit(false); self.current_table.set_dotted(false);